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

SPOJ1825 Free tour II 树分治

时间:2014-10-09 14:47:54      阅读:236      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   io   os   ar   for   sp   

题意:带边权树上有白点和黑点,问你最多不经过k个黑点使得路径最长(注意,路径有负数)

解题思路:基于树的点分治。数的路径问题,具体看09QZC论文,特别注意 当根为黑时的情况

解题代码:

bubuko.com,布布扣
  1 // File Name: spoj1825.cpp
  2 // Author: darkdream
  3 // Created Time: 2014年10月05日 星期日 20时20分33秒
  4 
  5 #include<vector>
  6 #include<list>
  7 #include<map>
  8 #include<set>
  9 #include<deque>
 10 #include<stack>
 11 #include<bitset>
 12 #include<algorithm>
 13 #include<functional>
 14 #include<numeric>
 15 #include<utility>
 16 #include<sstream>
 17 #include<iostream>
 18 #include<iomanip>
 19 #include<cstdio>
 20 #include<cmath>
 21 #include<cstdlib>
 22 #include<cstring>
 23 #include<ctime>
 24 #define LL long long 
 25 #define maxn 200005
 26 using namespace std;
 27 struct node{
 28     int ne;
 29     int w;
 30     node(int _ne,int _w)
 31     {
 32         ne = _ne ; 
 33         w = _w;
 34     }
 35 };
 36 int n ,K, m ; 
 37 int col[maxn];
 38 int vis[maxn];
 39 vector <node> mp[maxn];
 40 int sum[maxn];
 41 int mx[maxn];
 42 int cnum[maxn];
 43 void getsize(int k,int la)
 44 {
 45     sum[k] = 1; 
 46     mx[k] = 0;
 47     if(col[k])
 48     {
 49        cnum[k] = 1;
 50     }else cnum[k] = 0; 
 51     int num = mp[k].size();
 52     int tt = 0 ;
 53     for(int i = 0 ;i < num;i ++)
 54     {
 55        if(!vis[mp[k][i].ne] && mp[k][i].ne != la)
 56        {
 57            getsize(mp[k][i].ne,k);
 58            mx[k] = max(sum[mp[k][i].ne],mx[k]);
 59            sum[k] += sum[mp[k][i].ne];
 60           if(cnum[mp[k][i].ne] > tt)
 61               tt = cnum[mp[k][i].ne];
 62        }
 63     }
 64     cnum[k] += tt;
 65     
 66 }
 67 int root;
 68 int mxv; 
 69 int getroot(int k,int la ,int tans)
 70 {
 71      int tt = max(tans - sum[k],mx[k]);
 72      if(tt < mxv)
 73      {
 74         mxv = tt;
 75         root = k ; 
 76      }
 77      int num = mp[k].size();
 78      for(int i = 0 ;i < num ;i ++)
 79      {
 80        if(!vis[mp[k][i].ne] && mp[k][i].ne != la)
 81        {
 82            getroot(mp[k][i].ne,k,tans);
 83        }
 84      }
 85 }
 86 LL ans = 0 ;
 87 LL dp[maxn];
 88 LL tdp[maxn];
 89 bool cmp(node a, node b)
 90 {
 91     return cnum[a.ne] < cnum[b.ne];
 92 }
 93 void getdep(int k ,int la,int tc,LL dep)
 94 { 
 95 //    printf("%d %d %d %lld\n",la,k,tc,dep);
 96     int st = (col[k] == 1?1:0) ;
 97     tdp[tc+st] = max(tdp[tc+st],dep); //这个点是G点的时候
 98     int num = mp[k].size();
 99     for(int i = 0 ;i < num ;i ++)
100     {
101         if(!vis[mp[k][i].ne] && mp[k][i].ne != la )
102         {
103     //        printf("****%lld %d\n",dep,mp[k][i].w);
104             getdep(mp[k][i].ne,k,tc + st,dep + mp[k][i].w);
105         }
106     }
107 }
108 void solve(int k)
109 {
110     //printf("*****%d\n",k);
111     getsize(k,0);
112     mxv = 1e9;
113     getroot(k,0,sum[k]);
114     k = root;
115     int num = mp[k].size();
116     memset(dp,0,(cnum[k]+3)*sizeof(LL));
117     int tk ;
118     int st = 0 ;
119     if(col[k])
120     {
121         tk = K + 1;
122         st = 1;
123     }
124     else tk = K ;
125     int la =0 ; 
126     //int size = min(cnum[k],K);
127     sort(mp[k].begin(),mp[k].end(),cmp);
128     for(int i = 0 ;i < num ;i ++)
129     {
130         if(vis[mp[k][i].ne])
131             continue;
132         memset(tdp,0,(cnum[mp[k][i].ne]+3)*sizeof(tdp[0]));
133         
134         if(col[k])
135         getdep(mp[k][i].ne,k,1,mp[k][i].w);        
136         else 
137         getdep(mp[k][i].ne,k,0,mp[k][i].w);        
138     //    printf("**********%d\n",tk);
139         
140         
141         int tt = min(cnum[mp[k][i].ne]+st,K);    
142         for(int j = st ;j <= tt;j ++)
143         {
144            if(tk - j <= la)
145            {
146             if(tdp[j] + dp[tk-j]> ans)
147             {
148                 ans = tdp[j] + dp[tk-j];
149             }
150            }else{
151              if(tdp[j] + dp[la]> ans)
152              {
153                 ans = tdp[j] + dp[la];
154              }
155            }
156         } 
157         
158         dp[0] = max(dp[0],tdp[0]);
159         //printf("%d %d\n",n,cnum[mp[k][i].ne]);
160         /*if(tdp[tt+st+1] != 0)
161         {
162           printf("&&&&&&&&&&&&&&\n");
163         }*/
164         for(int j = 1 ;j <= tt+st; j ++)
165         {
166             dp[j] = max(dp[j],tdp[j]);
167             dp[j] = max(dp[j],dp[j-1]);
168         }
169         la = tt + st;
170     }
171     //puts("**********8");
172     vis[k] = 1;
173     for(int i = 0;i < num;i ++)
174     {
175         if(!vis[mp[k][i].ne])
176             solve(mp[k][i].ne);
177     }
178     return; 
179 }
180 int main(){
181    // freopen("out","r",stdin);    
182    scanf("%d %d %d",&n,&K,&m);
183     int temp ; 
184     memset(vis,0,sizeof(vis));
185     memset(col,0,sizeof(col));
186     for(int i = 1;i <= n;i ++)
187         mp[i].clear();
188     for(int i = 1;i <= m;i ++)
189     {
190         scanf("%d",&temp);
191         col[temp]  = 1;  
192     }
193     for(int i = 1;i <= n - 1;i ++)
194     {
195         int a, b , w; 
196         scanf("%d %d %d",&a,&b,&w);
197         mp[a].push_back(node(b,w));
198         mp[b].push_back(node(a,w));
199     }
200     ans = 0; 
201     solve(1);
202     printf("%lld\n",ans);
203     return 0;
204 }
View Code

 

SPOJ1825 Free tour II 树分治

标签:style   blog   http   color   io   os   ar   for   sp   

原文地址:http://www.cnblogs.com/zyue/p/4013037.html

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