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 }