http://acm.zju.edu.cn/onlinejudge/showContestProblems.do?contestId=358
The 2014 ACM-ICPC Asia Mudanjiang Regional Contest
|
136 - The 2014 ACM-ICPC Asia Mudanjiang Regional Contest
|
题意:给出一个树,找两个点建消防站,使离最近的消防站的距离最远的点的这个距离最小。点有20W个。
题解:这2个消防站肯定在树的直径上,二分这个距离d,分别把2个消防站放在与直径的2个端点距离d的位置。
20W个点,不碉的深搜会Segment Fault,我的深搜可是加了const &的碉深搜,才能过的。
听说的更碉的题解:在直径的中点把树切成两半,分别求直径中点,就得了。
代码:
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 #define ll long long 14 #define usll unsigned ll 15 #define mz(array) memset(array, 0, sizeof(array)) 16 #define mf1(array) memset(array, -1, sizeof(array)) 17 #define minf(array) memset(array, 0x3f, sizeof(array)) 18 #define REP(i,n) for(i=0;i<(n);i++) 19 #define FOR(i,x,n) for(i=(x);i<=(n);i++) 20 #define RD(x) scanf("%d",&x) 21 #define RD2(x,y) scanf("%d%d",&x,&y) 22 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 23 #define WN(x) printf("%d\n",x); 24 #define RE freopen("D.in","r",stdin) 25 #define WE freopen("huzhi.txt","w",stdout) 26 #define mp make_pair 27 #define pb push_back 28 #define pf push_front 29 #define ppf pop_front 30 #define ppb pop_back 31 const double pi=acos(-1.0); 32 const double eps=1e-10; 33 34 const int maxn=222222; 35 const int maxm=2*maxn; 36 37 int n; 38 39 struct Edge { 40 int v,next; 41 } e[maxm]; 42 int en,head[maxn]; 43 44 inline void add(const int &x,const int &y) { 45 e[en].v=y; 46 e[en].next=head[x]; 47 head[x]=en++; 48 } 49 50 int ans[3]; 51 52 int anode,bnode; 53 int len; 54 inline void dfs1(const int &x,const int &f,const int &step) { 55 if(step>len) { 56 len=step; 57 anode=x; 58 } 59 for(int i=head[x]; i!=-1; i=e[i].next) { 60 if(e[i].v != f) dfs1(e[i].v , x , step+1); 61 } 62 } 63 64 bool flag; 65 int b[maxn],bn; 66 inline void dfs2(const int &x,const int &f) { 67 if(x==bnode) { 68 flag=1; 69 b[bn++]=x; 70 return; 71 } 72 for(int i=head[x]; i!=-1; i=e[i].next) { 73 if(e[i].v != f) { 74 dfs2(e[i].v , x); 75 if(flag) { 76 b[bn++]=x; 77 return; 78 } 79 } 80 } 81 } 82 83 int _dis; 84 int u[maxn]; 85 86 inline void dfs3(const int &x,const int &f,const int &step){ 87 if(step>_dis) { 88 return; 89 } 90 u[x]=1; 91 for(int i=head[x]; i!=-1; i=e[i].next) { 92 if(e[i].v != f) dfs3(e[i].v , x , step+1); 93 } 94 } 95 96 inline bool ok(const int &dis){ 97 int i; 98 int nodec=b[dis]; 99 int noded=b[bn-1-dis]; 100 len=0; 101 _dis=dis; 102 memset(u,0,sizeof(u)); 103 dfs3(nodec,-1,0); 104 dfs3(noded,-1,0); 105 FOR(i,1,n)if(!u[i])return 0; 106 return 1; 107 } 108 inline void farm() { 109 int i; 110 len=0; 111 dfs1(1,-1,0); 112 //printf("%d!\n",anode); 113 bnode=anode; 114 len=0; 115 dfs1(bnode,-1,0); 116 //printf("%d!\n",anode); 117 flag=0,bn=0; 118 dfs2(anode,-1); 119 // FOR(i,0,bn-1)printf("%d ,",b[i]); 120 // printf("(a=%d , b=%d)\n",anode,bnode); 121 122 int an; 123 int l=0,r=bn-1,mid; 124 while(l<=r){ 125 mid=(l+r)>>1; 126 // printf("%d,%d,%d\n",l,mid,r); 127 if(ok(mid))r=mid-1,an=mid; 128 else l=mid+1; 129 } 130 ans[0]=an; 131 ans[1]=b[an]; 132 ans[2]=b[bn-1-an]; 133 if(ans[1]==ans[2])ans[2]=(ans[1])%n+1; 134 return; 135 } 136 137 int main() { 138 //re; 139 int T; 140 int i,j,x,y; 141 scanf("%d",&T); 142 while(T--) { 143 scanf("%d",&n); 144 memset(head,-1,sizeof(head)); 145 en=0; 146 REP(i,n-1) { 147 scanf("%d%d",&x,&y); 148 add(x,y); 149 add(y,x); 150 } 151 farm(); 152 printf("%d %d %d\n",ans[0],ans[1],ans[2]); 153 } 154 return 0; 155 }