HDU4871 Shortest-path tree(最短路径树 + 树的点分治)

题目大概要先求一张边有权的图的根为1的最短路径树,要满足根到各点路径序列的字典序最小;然后求这棵最短路径树包含k个结点的最长路径的长度和个数。

首先先构造出这棵字典序最小的最短路径树。。好吧,我太傻逼了,不会。。保证邻接表存储邻接点有序的前提下,就能按字典序DFS一遍,在O(N+E)的时间复杂度上构造出来了。

然后就是统计路径最长长度和方案数,树上路径问题当然就是树分治了。

不多谈。。%¥……¥%……¥……连续写了200多行然后一直出数据调了2个多小时才AC。。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 #include<algorithm>
  5 using namespace std;
  6 #define INF (1<<30)
  7 #define MAXN 33333
  8 #define MAXM 66666*2
  9 
 10 struct Edge{
 11     int v,w,next;
 12 }edge[MAXM];
 13 int NE,head[MAXN];
 14 void addEdge(int u,int v,int w){
 15     edge[NE].v=v; edge[NE].w=w;
 16     edge[NE].next=head[u]; head[u]=NE++;
 17 }
 18 
 19 int d[MAXN];
 20 bool vis[MAXN];
 21 void SPFA(int n){
 22     for(int i=1; i<=n; ++i){
 23         d[i]=INF; vis[i]=0;
 24     }
 25     d[1]=0; vis[1]=1;
 26     queue<int> que;
 27     que.push(1);
 28     while(!que.empty()){
 29         int u=que.front(); que.pop();
 30         for(int i=head[u]; i!=-1; i=edge[i].next){
 31             int v=edge[i].v;
 32             if(d[v]>d[u]+edge[i].w){
 33                 d[v]=d[u]+edge[i].w;
 34                 if(!vis[v]){
 35                     vis[v]=1;
 36                     que.push(v);
 37                 }
 38             }
 39         }
 40         vis[u]=0;
 41     }
 42 }
 43 
 44 struct Node{
 45     int u,v,w;
 46     bool operator<(const Node &nd)const{
 47         if(u==nd.u) return nd.v<v;
 48         return u<nd.u;
 49     }
 50 }node[MAXM];
 51 int cnt;
 52 
 53 void dfs(int u){
 54     vis[u]=1;
 55     for(int i=head[u]; i!=-1; i=edge[i].next){
 56         int v=edge[i].v;
 57         if(vis[v] || d[u]+edge[i].w!=d[v]) continue;
 58         node[cnt].u=u; node[cnt].v=v; node[cnt].w=edge[i].w;
 59         ++cnt;
 60         dfs(v);
 61     }
 62 }
 63 
 64 int size[MAXN];
 65 void getsize(int u,int fa){
 66     size[u]=1;
 67     for(int i=head[u]; i!=-1; i=edge[i].next){
 68         int v=edge[i].v;
 69         if(vis[v] || v==fa) continue;
 70         getsize(v,u);
 71         size[u]+=size[v];
 72     }
 73 }
 74 int mini,cen;
 75 void getcen(int u,int fa,int &tot){
 76     int res=tot-size[u];
 77     for(int i=head[u]; i!=-1; i=edge[i].next){
 78         int v=edge[i].v;
 79         if(vis[v] || v==fa) continue;
 80         res=max(res,size[v]);
 81         getcen(v,u,tot);
 82     }
 83     if(res<mini){
 84         mini=res;
 85         cen=u;
 86     }
 87 }
 88 int getcen(int u){
 89     getsize(u,u);
 90     mini=INF;
 91     getcen(u,u,size[u]);
 92     return cen;
 93 }
 94 
 95 int k;
 96 int a_val[MAXN],a_cnt[MAXN],a_rec[MAXN],an,b_val[MAXN],b_cnt[MAXN],b_rec[MAXN],bn;
 97 bool tag[MAXN];
 98 int ans_val,ans_cnt;
 99 void conqur_dfs(int u,int fa,int val,int tot){
100     if(b_val[tot]<val){
101         b_val[tot]=val;
102         b_cnt[tot]=1;
103         if(!tag[tot]){
104             tag[tot]=1;
105             b_rec[bn++]=tot;
106         }
107     }else if(b_val[tot]==val){
108         ++b_cnt[tot];
109     }
110     for(int i=head[u]; i!=-1; i=edge[i].next){
111         int v=edge[i].v;
112         if(vis[v] || v==fa) continue;
113         conqur_dfs(v,u,val+edge[i].w,tot+1);
114     }
115 }
116 void conqur(int u){
117     an=0;
118     for(int i=head[u]; i!=-1; i=edge[i].next){
119         int v=edge[i].v;
120         if(vis[v]) continue;
121         bn=0;
122         conqur_dfs(v,v,edge[i].w,1);
123         for(int j=0; j<bn; ++j){
124             if(b_rec[j]==k-1){
125                 if(b_val[b_rec[j]]>ans_val){
126                     ans_val=b_val[b_rec[j]];
127                     ans_cnt=b_cnt[b_rec[j]];
128                 }else if(b_val[b_rec[j]]==ans_val){
129                     ans_cnt+=b_cnt[b_rec[j]];
130                 }
131             }else if(b_rec[j]<k-1){
132                 int tmp=k-1-b_rec[j];
133                 if(a_cnt[tmp]==0) continue;
134                 if(b_val[b_rec[j]]+a_val[tmp]>ans_val){
135                     ans_val=b_val[b_rec[j]]+a_val[tmp];
136                     ans_cnt=b_cnt[b_rec[j]]*a_cnt[tmp];
137                 }else if(b_val[b_rec[j]]+a_val[tmp]==ans_val){
138                     ans_cnt+=b_cnt[b_rec[j]]*a_cnt[tmp];
139                 }
140             }
141         }
142         for(int j=0; j<bn; ++j){
143             int tmp=b_rec[j];
144             tag[tmp]=0;
145             a_rec[an++]=tmp;
146             if(a_val[tmp]<b_val[tmp]){
147                 a_val[tmp]=b_val[tmp];
148                 a_cnt[tmp]=b_cnt[tmp];
149             }else if(a_val[tmp]==b_val[tmp]){
150                 a_cnt[tmp]+=b_cnt[tmp];
151             }
152             b_val[tmp]=0;
153             b_cnt[tmp]=0;
154         }
155     }
156     for(int i=0; i<an; ++i){
157         a_val[a_rec[i]]=0;
158         a_cnt[a_rec[i]]=0;
159     }
160 }
161 
162 void divide(int u){
163     u=getcen(u);
164     vis[u]=1;
165     conqur(u);
166     for(int i=head[u]; i!=-1; i=edge[i].next){
167         int v=edge[i].v;
168         if(vis[v]) continue;
169         divide(v);
170     }
171 }
172 
173 int main(){
174     int t,n,m,a,b,c;
175     scanf("%d",&t);
176     while(t--){
177         NE=0;
178         memset(head,-1,sizeof(head));
179         scanf("%d%d%d",&n,&m,&k);
180         for(int i=0; i<m; ++i){
181             scanf("%d%d%d",&a,&b,&c);
182             node[i<<1].u=a; node[i<<1].v=b; node[i<<1].w=c;
183             node[i<<1|1].u=b; node[i<<1|1].v=a; node[i<<1|1].w=c;
184         }
185         sort(node,node+(m<<1));
186         for(int i=0; i<(m<<1); ++i){
187             addEdge(node[i].u,node[i].v,node[i].w);
188         }
189         SPFA(n);
190         cnt=0;
191         memset(vis,0,sizeof(vis));
192         dfs(1);
193         NE=0;
194         memset(head,-1,sizeof(head));
195         for(int i=0; i<cnt; ++i){
196             addEdge(node[i].u,node[i].v,node[i].w);
197             addEdge(node[i].v,node[i].u,node[i].w);
198         }
199         memset(vis,0,sizeof(vis));
200         ans_val=0; ans_cnt=0;
201         divide(1);
202         printf("%d %d\n",ans_val,ans_cnt);
203     }
204     return 0;
205 }

 

posted @ 2016-05-10 10:45  WABoss  阅读(716)  评论(0编辑  收藏  举报