51nod 1273 旅行计划(思维题)

  一开始看到这题真的有点懵逼...一直在想着套算法,结果题解除了sort和dfs其他什么都没用到

  显然每次到达的一定都是叶子,先从根节点dfs一遍,按深度对叶子降序排序,按这个顺序向根节点dfs,路径上没有被之前的叶子遍历过的点就是到达这个叶子时未经过的点的个数,于是我们跑出所有叶子未经过点的个数再排序一次输出就行了

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
#define ll long long 
using namespace std;
const int maxn=500010,inf=1e9;
struct tjm{int too,pre;}e[maxn];
struct poi{int w,pos;}a[maxn],b[maxn];
int n,x,tot,cnt,root,t;
int last[maxn];
bool v[maxn];
void read(int &k)
{
    int f=1;k=0;char c=getchar();
    while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
    k*=f;
}
inline bool cmp(poi a,poi b){return a.w==b.w?a.pos<b.pos:a.w>b.w;}
inline void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}
inline void dfs(int x,int dep,int fa)
{
    bool flag=0;
    for(int i=last[x];i;i=e[i].pre)
    if(e[i].too!=fa)dfs(e[i].too,dep+1,x),flag=1;
    if((!flag)&&x!=root)a[++cnt].pos=x,a[cnt].w=dep;
}
inline bool dfs2(int x,int fa)
{
    if(x==root||v[x])return 1;
    for(int i=last[x];i;i=e[i].pre)
    if(e[i].too!=fa)if(dfs2(e[i].too,x))return t++,v[x]=1,1;
    return 0;
}
int main()
{
    read(n);read(root);
    for(int i=1;i<n;i++)read(x),add(x,i),add(i,x);
    dfs(root,0,-1);sort(a+1,a+1+cnt,cmp);
    for(int i=1;i<=cnt;i++)
    {
        t=0;b[i].pos=a[i].pos;
        dfs2(a[i].pos,-1);
        b[i].w=t;
    }
    sort(b+1,b+1+cnt,cmp);
    printf("%d
",root);for(int i=1;i<=cnt;i++)printf("%d
",b[i].pos);
    return 0;
}
View Code

先分析,再做题!

原文地址:https://www.cnblogs.com/Sakits/p/7388172.html