跟poj 1114差不多的题。。。求是否存在长为X的路径
开始的时候是vector建边,但是超时了,最后找来找去发现是clear的次数太多了,无奈之下,还是换回朴素建边了,哎,以后数据量大的题还是避免STL吧
自己写的calc函数挫的要死,于是从网上淘了一个清晰的。。。
http://blog.csdn.net/sdj222555/article/details/7908842
#include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int maxn = 22222; struct Divided_Conquer { struct Edge{ int v , w , next; Edge(){} Edge(int v,int w): v(v),w(w) { } }edge[maxn]; int E ; void add_edge(int a,int b,int w) { edge[E].v = b; edge[E].w = w; edge[E].next = head[a]; head[a] = E++; } int head[maxn]; bool Del[maxn]; int N , K; int size[maxn] , opt[maxn]; int tnode[maxn] , tns; int all[maxn] , as; void Dfs(int u,int f) { tnode[tns++] = u; size[u] = 1; opt[u] = 0; for(int i=head[u];~i;i=edge[i].next) { int v = edge[i].v; if(!Del[v] && v != f) { Dfs(v,u); size[u] += size[v]; opt[u] = max(opt[u],size[v]); } } } int Get_Root(int u) { tns = 0; Dfs(u,-1); int mi = maxn , ans = -1; for(int i = 0; i < tns; i++){ opt[tnode[i]] = max(opt[tnode[i]],size[u]-size[tnode[i]]) ; if(opt[tnode[i]] < mi) { mi = opt[tnode[i]]; ans = tnode[i]; } } return ans; } void Get_Dis(int u,int len,int fa) { all[as++] = len; for(int i=head[u];~i;i=edge[i].next){ int v = edge[i].v; if(!Del[v] && v != fa) { Get_Dis(v,len+edge[i].w,u); } } } void Solve(int u) { u = Get_Root(u); int nch = 0; Ans += Calc(u,0,true); Del[u] = true; for(int i=head[u];~i;i=edge[i].next) { int v = edge[i].v; if(!Del[v]) { Ans -= Calc(v,edge[i].w,false); Solve(v); } } } inline long long Calc(int u,int w,bool f) { int pt = 0 ; long long sum = 0 ; as = 0; Get_Dis(u,w,-1); sort(all,all+as); if(f) for(int i = 0; i < as; i++) if(all[i]==K) sum++;//单个点到根 int i = all[0] ? 0 : 1, j = as - 1; while(i < j) //一对点 { if(all[i] + all[j] < K) i++; else if(all[i] + all[j] > K) j--; else { if(all[i] == all[j]) { sum += (j - i) * (j - i + 1) / 2; break; } int st = i, ed = j; while(all[st] == all[i]) st++; while(all[ed] == all[j]) ed--; sum += (st - i) * (j - ed); i = st, j = ed; } } return sum; } void Ini() { int a,b,c; fill(head,head+N+1,-1); E = 0; for(int i = 1; i <= N; i++) { while(scanf("%d",&a)!=EOF && a) { scanf("%d",&b); add_edge(i,a,b); add_edge(a,i,b); } } while(scanf("%d",&K)!=EOF && K) { Ans = 0; fill(Del,Del+N+1,false); Solve(1); if(Ans) printf("AYE\n"); else printf("NAY\n"); } printf(".\n"); } long long Ans; }sol; int main() { while(scanf("%d",&sol.N)!=EOF && sol.N) { sol.Ini(); } return 0; } /* 7 1 2 3 1 3 1 2 4 3 2 5 3 3 6 1 3 7 3 2 */