题目链接:
https://codeforces.com/contest/1182/problem/D
题目大意:
让你找到一个点,使得剩下的所有点满足 任意两个点v1,v2.;如果dis(v1,rt)==dis(v2,rt),则连向v1的边的个数等于连向v2的边的个数。
具体思路:
思路一:
先找到树的重心,然后从这个重心开始,找一条单链(这条链上的节点度都为2),然后这条链上最远的点和最近的点;只需要检验这三个点就可以了。
思路二:
通过对树进行一个拓扑序,找到第n次找到的点(有点对称的感觉)。然后剩下的就是和思路一后半段相同了。
ps:我也不知道咋证明,,画了好多图都是符合的,等以后有机会补上证明把(咕咕咕)
AC代码::
1 #include<iostream> 2 #include<cmath> 3 #include<stack> 4 #include<stdio.h> 5 #include<algorithm> 6 #include<queue> 7 #include<vector> 8 #include<cstring> 9 using namespace std; 10 # define inf 0x3f3f3f3f 11 # define ll long long 12 const int maxn = 2e5+100; 13 vector<int>Edge[maxn]; 14 int in[maxn],degree[maxn]; 15 int n; 16 int topu() 17 { 18 queue<int>q; 19 int num=0; 20 for(int i=1; i<=n; i++) 21 { 22 if(in[i]==1) 23 { 24 num++; 25 q.push(i); 26 } 27 } 28 int rt=0; 29 while(!q.empty()) 30 { 31 int top=q.front(); 32 q.pop(); 33 for(int i=0; i<Edge[top].size(); i++) 34 { 35 int to=Edge[top][i]; 36 if(in[to]==1)continue;; 37 if(--in[to]==1) 38 { 39 q.push(to); 40 if(++num==n) 41 rt=to; 42 } 43 } 44 } 45 return rt; 46 } 47 int dis[maxn]; 48 int deg[maxn]; 49 bool judge(int rt) 50 { 51 memset(dis,0,sizeof(dis)); 52 memset(deg,0,sizeof(deg)); 53 dis[rt]=1; 54 queue<int>q; 55 q.push(rt); 56 while(!q.empty()) 57 { 58 int top=q.front(); 59 q.pop(); 60 for(int i=0; i<Edge[top].size(); i++){ 61 int to=Edge[top][i]; 62 if(!dis[to]) 63 q.push(to); 64 if(!dis[to]) 65 { 66 dis[to]=dis[top]+1; 67 } 68 if(!deg[dis[to]]) 69 deg[dis[to]]=degree[to]; 70 if(deg[dis[to]]!=degree[to]) 71 return false; 72 } 73 } 74 return true; 75 } 76 int len[maxn]; 77 void dfs(int v,int rt,int dep) 78 { 79 if(degree[v]>2) 80 return ; 81 if(degree[v]==1){ 82 len[v]=dep; 83 return ; 84 } 85 for(int i=0; i<Edge[v].size(); i++) 86 { 87 int to=Edge[v][i]; 88 if(to==rt) 89 continue; 90 dfs(to,v,dep+1); 91 } 92 } 93 int main() 94 { 95 int st,ed; 96 scanf("%d",&n); 97 if(n==1){ 98 printf("1\n"); 99 return 0; 100 } 101 for(int i=1; i<n; i++) 102 { 103 scanf("%d %d",&st,&ed); 104 Edge[st].push_back(ed); 105 Edge[ed].push_back(st); 106 in[st]++,in[ed]++; 107 degree[st]++,degree[ed]++; 108 } 109 int rt=topu(); 110 if(judge(rt)) 111 { 112 printf("%d\n",rt); 113 //cout<<rt<<endl; 114 return 0; 115 } 116 for(int i=0; i<Edge[rt].size(); i++) 117 { 118 int to=Edge[rt][i]; 119 dfs(to,rt,1); 120 } 121 int mx=0,id=-1; 122 for(int i=1; i<=n; i++) 123 { 124 if(len[i]&&len[i]>mx) 125 { 126 mx=len[i]; 127 id=i; 128 } 129 } 130 if(id!=-1) 131 { 132 if(judge(id)) 133 { 134 printf("%d\n",id); 135 return 0; 136 } 137 } 138 int minx=inf ; 139 id=-1; 140 for(int i=1; i<=n; i++) 141 { 142 if(len[i]&&len[i]<minx) 143 { 144 minx=len[i]; 145 id=i; 146 } 147 } 148 if(id!=-1) 149 { 150 if(judge(id)) 151 { 152 printf("%d\n",id); 153 return 0; 154 } 155 } 156 printf("-1\n"); 157 return 0; 158 }