bzoj3206 [Apio2013]道路费用
Posted wfj_2048
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3206 [Apio2013]道路费用相关的知识,希望对你有一定的参考价值。
Description
Input
第一行包含三个由空格隔开的整数N,M和K。接下来的 M行描述最开始的M 条道路
。这M行中的第i行包含由空格隔开的整数ai,bi和c i,表示有一条在a i和b i之间,费用为c i的双向道路。接下
来的K行描述新建的K条道路。这 K行中的第i行包含由空格隔开的整数 xi和yi,表示有一条连接城镇xi和yi新道路
。最后一行包含N个由空格隔开的整数,其中的第j个为pj,表示从城镇j 前往城镇 1的人数。输入也满足以下约束
条件。1 ≤ N ≤ 100000;1 ≤ K ≤ 20;1 ≤ M ≤ 300000;对每个i和j,1 ≤ ci, pj ≤ 10^6;
Output
你的程序必须输出恰好一个整数到标准输出,表示能获得的最大的收入。
Sample Input
5 5 1
3 5 2
1 2 3
2 3 5
2 4 4
4 3 6
1 3
10 20 30 40 50
3 5 2
1 2 3
2 3 5
2 4 4
4 3 6
1 3
10 20 30 40 50
Sample Output
400
HINT
在样例中, Mr. Greedy应该将新道路(1,3)的费用设置为 5分钱。在这个费用下,他可以选择道路(3,5),(1,2),(2,4)和(1,3)来最小化总费用,这个费用为 14。从城镇 3出发的 30个人和从城镇 5出发的 50个人将经过新道路前往城镇 1,因此他可以获得为(30+50)_5=400 分钱的最好收入。如果我们这样做,将新道路(1,3)的费用设置为 10分钱。根据传统的限制,Mr. Greedy必须选择(3,5),(1,2),(2,4)和(2,3),因为这是唯一费用最小的集合。因此,在嘉年华的过程中道路(1,3)将没有任何收入。
正解:最小生成树+搜索。
这道题还是有点码的,我写了好久。。
首先$k\leq20$,我们可以想到枚举选边的集合,然后计算答案。
但是有一个问题,原图特别大,我们每次选边计算答案肯定不行,怎么办呢?
我们可以发现,有一些边是无论如何都会在原图上的,我们只要强制把$k$条边先加进去,再看有哪些边可以和这$k$条边构成最小生成树就行了。
然后我们可以把原图缩点变成一个$k+1$个点的图,但是边数还是$k^{2}$级别的。
那么我们可以再去掉那$k$条边,做一遍最小生成树,这样的边是会出现在原图上的,其他边肯定不会在图上,然后边数就变成$k$条了。
然后我们枚举$k$条边是否在图上,强制把搜索出来的边加进图中,再看这些边的取值。
只要把没加进图的边在树上走一下,经过的边边权取个$min$就行了。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define N (300010) 6 7 using namespace std; 8 9 struct E{ int u,v,w; }gg[N],g[N],e[N]; 10 11 int bel[N],a[N],st[N],fa[N],vis[N],n,m,k,top,cnt,ecnt; 12 ll val[N],ans; 13 14 il int gi(){ 15 RG int x=0,q=1; RG char ch=getchar(); 16 while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar(); 17 if (ch==‘-‘) q=-1,ch=getchar(); 18 while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); 19 return q*x; 20 } 21 22 il int cmp(const E &a,const E &b){ return a.w<b.w; } 23 24 il int find(RG int x){ return fa[x]==x ? x : fa[x]=find(fa[x]); } 25 26 struct graph{ 27 28 struct edge{ int nt,to,fg; }g[N<<1]; 29 30 int head[N],fa[N],dep[N],dis[N],num; 31 ll sz[N]; 32 33 il void insert(RG int from,RG int to,RG int fg){ 34 g[++num]=(edge){head[from],to,fg},head[from]=num; return; 35 } 36 37 il void dfs1(RG int x,RG int p){ 38 if (!bel[x]) bel[x]=++cnt; val[bel[x]]+=a[x]; RG int v; 39 for (RG int i=head[x];i;i=g[i].nt){ 40 v=g[i].to; if (v==p) continue; 41 if (g[i].fg) bel[v]=bel[x]; dfs1(v,x); 42 } 43 return; 44 } 45 46 il void dfs2(RG int x,RG int p){ 47 fa[x]=p,dep[x]=dep[p]+1,sz[x]=val[x],dis[x]=1<<30; RG int v; 48 for (RG int i=head[x];i;i=g[i].nt){ 49 v=g[i].to; if (v==p) continue; 50 dfs2(v,x),sz[x]+=sz[v]; 51 } 52 return; 53 } 54 55 il void getlca(RG int u,RG int v,RG int w){ 56 while (u!=v){ 57 if (dep[u]<dep[v]) swap(u,v); 58 dis[u]=min(dis[u],w),u=fa[u]; 59 } 60 return; 61 } 62 63 il ll getans(RG int x,RG int p){ 64 RG ll res=0; RG int v; 65 for (RG int i=head[x];i;i=g[i].nt){ 66 v=g[i].to; if (v==p) continue; 67 res+=getans(v,x)+1LL*(!g[i].fg)*dis[v]*sz[v]; 68 } 69 return res; 70 } 71 72 }G; 73 74 il ll check(){ 75 for (RG int i=1;i<=cnt;++i) fa[i]=i,G.head[i]=0; G.num=0; 76 for (RG int i=1,x,y;i<=top;++i){ 77 x=find(e[st[i]].u),y=find(e[st[i]].v); 78 if (x!=y) fa[x]=y,G.insert(e[st[i]].u,e[st[i]].v,0),G.insert(e[st[i]].v,e[st[i]].u,0); 79 } 80 for (RG int i=1,x,y;i<=m;++i){ 81 x=find(g[i].u),y=find(g[i].v),vis[i]=0; 82 if (x!=y) fa[x]=y,vis[i]=1,G.insert(g[i].u,g[i].v,1),G.insert(g[i].v,g[i].u,1); 83 } 84 G.dfs2(1,0); 85 for (RG int i=1;i<=m;++i) if (!vis[i]) G.getlca(g[i].u,g[i].v,g[i].w); 86 return G.getans(1,0); 87 } 88 89 il void dfs(RG int x){ 90 if (x>k) ans=max(ans,check()); 91 else st[++top]=x,dfs(x+1),--top,dfs(x+1); return; 92 } 93 94 int main(){ 95 #ifndef ONLINE_JUDGE 96 freopen("toll.in","r",stdin); 97 freopen("toll.out","w",stdout); 98 #endif 99 n=gi(),m=gi(),k=gi(); for (RG int i=1;i<=n;++i) fa[i]=i; 100 for (RG int i=1;i<=m;++i) g[i].u=gi(),g[i].v=gi(),g[i].w=gi(); 101 for (RG int i=1,x,y;i<=k;++i){ 102 e[i].u=gi(),e[i].v=gi(),x=find(e[i].u),y=find(e[i].v); 103 if (x!=y) fa[x]=y,G.insert(e[i].u,e[i].v,0),G.insert(e[i].v,e[i].u,0); 104 } 105 sort(g+1,g+m+1,cmp); 106 for (RG int i=1,x,y;i<=m;++i){ 107 x=find(g[i].u),y=find(g[i].v); 108 if (x!=y) fa[x]=y,vis[i]=1,G.insert(g[i].u,g[i].v,1),G.insert(g[i].v,g[i].u,1); 109 } 110 for (RG int i=1;i<=n;++i) a[i]=gi(),fa[i]=i; G.dfs1(1,0); 111 for (RG int i=1;i<=k;++i) e[i].u=bel[e[i].u],e[i].v=bel[e[i].v]; 112 for (RG int i=1,x,y;i<=m;++i){ 113 g[i].u=bel[g[i].u],g[i].v=bel[g[i].v]; 114 x=find(g[i].u),y=find(g[i].v),vis[i]=0; 115 if (x!=y) fa[x]=y,vis[i]=1,gg[++ecnt]=g[i]; 116 } 117 m=ecnt; for (RG int i=1;i<=m;++i) g[i]=gg[i]; 118 dfs(1),cout<<ans; return 0; 119 }
以上是关于bzoj3206 [Apio2013]道路费用的主要内容,如果未能解决你的问题,请参考以下文章