ural 1056 Computer Net

    技术2024-12-17  8

    原本想找一个DP的方法, 可惜答案鱼龙混杂, 良莠不齐, 从BYVoid牛上拷下的代码都是CE.....

    无奈, 还是DFS吧.

    先找一个点, 然后找到任一个距离其最远的点, 再以这点为起点搜索距其最远的点, 这两个点之间的路径就是树网的直径__之一.

     

    我咨询奇异夸克大牛时, 他想到的是贪心的方法.

    先搜一遍, 然后分情况讨论.

    1. 若此时有数个点距起点最远, 那么起点就是中心, 且唯一.

    2. 否则, 向那个最远点所在的子树靠近, 距这棵子树上的点距离-1,同深度其他子树+1.

    这个算法真的很好(它比两次DFS的理由清晰得多, 复杂度也低), 不过像我这样的菜, 实现它是有一定难度的......以后再说.

    #include<iostream> using namespace std; int n; int first[10001]; int nexti[20001],u[20001],v[20001]; int dep[10001],last[10001]; int tot,maxi,flag,temp; int want1,want2; void input(int i,int j) { u[++tot]=j; v[tot]=i; nexti[tot]=first[j]; first[j]=tot; return; } void search(int a,int len) { if(len&1) while(1) { if(dep[a]==(len+1)/2) { want1=a; return; } a=last[a]; } else while(1) { if(dep[a]<len/2) return; if(dep[a]==len/2+1) want1=a; if(dep[a]==len/2) want2=a; a=last[a]; } } void dfs(int p,int num) { int x,y; dep[p]=num; if(num>maxi) { maxi=num; flag=p; } x=first[p]; while(x) { y=v[x]; if(!dep[y]) { last[y]=p; dfs(y,num+1); } x=nexti[x]; } return; } int main() { int i,j,k; scanf("%d",&n); for(i=2;i<=n;i++) { scanf("%d",&j); input(i,j); input(j,i); } dfs(1,1); maxi=0; temp=flag; memset(dep,0,sizeof(dep)); memset(last,0,sizeof(last)); dfs(temp,1); search(flag,dep[flag]); if(dep[flag]&1) printf("%d/n",want1); else { if(want2<want1) swap(want1,want2); printf("%d %d/n",want1,want2); } return 0; }

    最新回复(0)