poj1741 树的分治
被这道题 深深的伤害到了……
http://poj.org/problem?id=1741
10985223 | asia2562219 | 1741 | Accepted | 1124K | 219MS | C++ | 2842B | 2012-11-03 23:59:11 |
刚开始使用LCA解决问题 ,华丽丽超时,无脑百度了下。
采用分治解决问题:
题目的情况分两种:
(1)两点间的路径经过根节点。
(2)两点属于根节点的同一颗子树下。
递归问题 ,所以只考虑第一种情况即可。dist[i]+dist[j]<=k 且 i和j 不在根节点的同一颗子树下;
对dist排序 可以在线性时间内求出符合的对数。
最最坑了我的是 分治时要找每颗树的重心。否则便是无尽的TEL……
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <algorithm> 5 #include <iostream> 6 using namespace std; 7 #define MAXN 11111 8 struct node 9 { 10 int vex; 11 int length; 12 int sum; 13 int maxv; 14 node *next; 15 }tree[MAXN*2],*head[MAXN],tp[MAXN]; 16 17 int visit[MAXN],dist[MAXN],size[MAXN],hash[MAXN]; 18 int n,k,tot,ans,root,ptr; 19 void init(int n) 20 { 21 ptr=0;ans=0; 22 for(int i=0;i<=n;i++) 23 { 24 visit[i]=0; 25 head[i]=NULL; 26 } 27 } 28 void dfs(int root,int fa) 29 { 30 tp[root].maxv=0;tp[root].sum=1; 31 node *it=head[root]; 32 while(it!=NULL) 33 { 34 if(!visit[it->vex]&&it->vex!=fa) 35 { 36 dfs(it->vex,root); 37 tp[root].sum+=tp[it->vex].sum; 38 tp[root].maxv=max(tp[root].maxv,tp[it->vex].sum); 39 } 40 it=it->next; 41 } 42 hash[tot]=root; 43 size[tot++]=tp[root].maxv; 44 } 45 void getdist(int now,int fa,int dis) 46 { 47 dist[tot++]=dis; 48 node *it=head[now]; 49 while(it!=NULL) 50 { 51 if(it->vex!=fa&&!visit[it->vex]&&dis+it->length<=k) 52 getdist(it->vex,now,dis+it->length); 53 it=it->next; 54 } 55 } 56 int getroot(int root) 57 { 58 tot=1; 59 dfs(root,0); 60 int minn=MAXN,maxn,mini,tn=tp[root].sum; 61 for(int i=1;i<tot;i++) 62 { 63 maxn=max(size[i],tn-size[i]); 64 if(minn>maxn){minn=maxn;mini=hash[i];} 65 } 66 return mini; 67 } 68 void getans() 69 { 70 sort(dist,dist+tot); 71 int left=1,right=tot-1; 72 while(left<right) 73 { 74 if(dist[left]+dist[right]<=k) 75 { 76 ans+=right-left;left++; 77 } 78 else right--; 79 } 80 } 81 void getans1(int root) 82 { 83 visit[root]=1; 84 node *it=head[root]; 85 while(it!=NULL) 86 { 87 if(!visit[it->vex]) 88 { 89 tot=1; 90 getdist(it->vex,root,it->length); 91 sort(dist,dist+tot); 92 int left=1,right=tot-1; 93 while(left<right) 94 { 95 if(dist[left]+dist[right]<=k) 96 { 97 ans-=right-left;left++; 98 } 99 else right--; 100 } 101 } 102 it=it->next; 103 } 104 } 105 void add(int x,int y,int l) 106 { 107 tree[ptr].vex=y; 108 tree[ptr].length=l; 109 tree[ptr].next=head[x]; 110 head[x]=&tree[ptr++]; 111 } 112 void cal(int now,int fa) 113 { 114 root=getroot(now); 115 tot=1; 116 getdist(root,0,0); 117 getans(); 118 getans1(root); 119 node *it=head[root]; 120 while(it!=NULL) 121 { 122 if(!visit[it->vex]&&it->vex!=fa) 123 { 124 cal(it->vex,root); 125 } 126 it=it->next; 127 } 128 } 129 int main() 130 { 131 while(scanf("%d%d",&n,&k),n!=0) 132 { 133 int x,y,l; 134 init(n); 135 for(int i=1;i<n;i++) 136 { 137 scanf("%d%d%d",&x,&y,&l); 138 add(x,y,l);add(y,x,l); 139 } 140 cal(1,0); 141 printf("%d\n",ans); 142 } 143 return 0; 144 }
怎么随便找的题 就这么牛逼呢 ?
实力还是不足啊!