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 }

怎么随便找的题 就这么牛逼呢 ?

实力还是不足啊!

posted @ 2012-11-04 00:14  TO_Asia  阅读(968)  评论(0编辑  收藏  举报