码迷,mamicode.com
首页 > 其他好文 > 详细

【点分治】hdu5016 Mart Master II

时间:2015-02-13 16:28:57      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:

点分治好题。

①手动开栈。

②dp预处理每个点被哪个市场控制,及其距离是多少,记作pair<int,int>数组p。

③设dis[u].first为u到重心s的距离,dis[u].second=u,到在统计的时候,若dis[u]<=(p[v].first-dis[v].first,p[v].second)(双关键字比较),则符合题意,当然这样在计算同一颗子树里的答案时,是压根不对的,但是既然这部分反正是要被减掉的,那就将错就错地计算即可了。

④最后在所有原非市场节点的ans中取一个最大的即可。

  1 #pragma comment(linker, "/STACK:1024000000,1024000000")
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cstdlib>
  6 using namespace std;
  7 #define MAXN 100001
  8 #define INF 1000000000
  9 typedef pair<int,int> Point;
 10 Point td[MAXN],ds[MAXN],p[MAXN],td2[MAXN],ds2[MAXN];
 11 bool is[MAXN];
 12 int n,K,ans[MAXN],en2,en3;
 13 int v[MAXN<<1],w[MAXN<<1],first[MAXN],next[MAXN<<1],en;
 14 void AddEdge(const int &U,const int &V,const int &W)
 15 {
 16     v[++en]=V;
 17     w[en]=W;
 18     next[en]=first[U];
 19     first[U]=en;
 20 }
 21 bool centroid[MAXN];
 22 int size[MAXN];
 23 int calc_sizes(int U,int Fa)
 24 {
 25     int res=1;
 26     for(int i=first[U];i;i=next[i])
 27       if(v[i]!=Fa&&(!centroid[v[i]]))
 28         res+=calc_sizes(v[i],U);
 29     return size[U]=res;
 30 }
 31 Point calc_centroid(int U,int Fa,int nn)
 32 {
 33     Point res=make_pair(INF,-1);
 34     int sum=1,maxv=0;
 35     for(int i=first[U];i;i=next[i])
 36       if(v[i]!=Fa&&(!centroid[v[i]]))
 37         {
 38           res=min(res,calc_centroid(v[i],U,nn));
 39           maxv=max(maxv,size[v[i]]);
 40           sum+=size[v[i]];
 41         }
 42     maxv=max(maxv,nn-sum);
 43     res=min(res,make_pair(maxv,U));
 44     return res;
 45 }
 46 void calc_dis(int U,int Fa,int d)
 47 {
 48     td[en2++]=make_pair(d,U);
 49     for(int i=first[U];i;i=next[i])
 50       if(v[i]!=Fa&&(!centroid[v[i]]))
 51         calc_dis(v[i],U,d+w[i]);
 52 }
 53 void calc_pairs(Point dis[],Point dis2[],int En,int op)
 54 {
 55     sort(dis2,dis2+En);
 56     for(int i=0;i<En;++i)
 57       ans[dis[i].second]+=(dis2+En-lower_bound(dis2,dis2+En,dis[i]))*op;
 58 }
 59 void solve(int U)
 60 {
 61     calc_sizes(U,-1);
 62     int s=calc_centroid(U,-1,size[U]).second;
 63     centroid[s]=1;
 64     for(int i=first[s];i;i=next[i])
 65       if(!centroid[v[i]])
 66         solve(v[i]);
 67     en3=0;
 68     ds[en3]=make_pair(0,s);
 69     ds2[en3++]=make_pair(p[s].first,p[s].second);
 70     for(int i=first[s];i;i=next[i])
 71       if(!centroid[v[i]])
 72         {
 73           en2=0; calc_dis(v[i],s,w[i]);
 74           for(int i=0;i<en2;++i)
 75             td2[i]=make_pair(p[td[i].second].first-td[i].first,p[td[i].second].second);
 76           calc_pairs(td,td2,en2,-1);
 77           memcpy(ds+en3,td,en2*sizeof(Point));
 78           memcpy(ds2+en3,td2,en2*sizeof(Point));
 79           en3+=en2;
 80         }
 81     calc_pairs(ds,ds2,en3,1);
 82     centroid[s]=0;
 83 }
 84 void init()
 85 {
 86     memset(ans,0,(n+1)*sizeof(int));
 87     memset(first,0,(n+1)*sizeof(int));
 88     en=0;
 89 }
 90 void dfs1(int U,int Fa)
 91 {
 92     for(int i=first[U];i;i=next[i])
 93       if(v[i]!=Fa)
 94         {
 95           p[v[i]]=min(p[v[i]],make_pair(p[U].first+w[i],p[U].second));
 96           dfs1(v[i],U);
 97         }
 98 }
 99 void dfs2(int U,int Fa)
100 {
101     for(int i=first[U];i;i=next[i])
102       if(v[i]!=Fa)
103         {
104           dfs2(v[i],U);
105           p[U]=min(p[U],make_pair(p[v[i]].first+w[i],p[v[i]].second));
106         }
107 }
108 int main()
109 {
110     int a,b,c;
111     while(scanf("%d",&n)!=EOF)
112       {
113           init();
114         for(int i=1;i<n;++i)
115             {
116               scanf("%d%d%d",&a,&b,&c);
117               AddEdge(a,b,c);
118               AddEdge(b,a,c);
119             }
120         for(int i=1;i<=n;++i)
121             {
122               scanf("%d",&is[i]);
123               if(!is[i]) p[i]=make_pair(INF,INF);
124               else p[i]=make_pair(0,i);
125             }
126         dfs2(1,-1);
127         dfs1(1,-1);
128         solve(1);
129         int Ans=0;
130         for(int i=1;i<=n;++i) if(!is[i]) Ans=max(Ans,ans[i]);
131         printf("%d\n",Ans);
132       }
133     return 0;
134 }

 

【点分治】hdu5016 Mart Master II

标签:

原文地址:http://www.cnblogs.com/autsky-jadek/p/4290353.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!