[BZOJ3206][APIO2013]道路费用(最小生成树)

3206: [Apio2013]道路费用

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 568  Solved: 266
[Submit][Status][Discuss]

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

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)将没有任何收入。

Source

[Submit][Status][Discuss]

这种题一般不是数据结构+分类讨论,就是缩图。

1.首先把K条边全部选上,这个时候图可能仍然不连通,于是将M条原边排序,从小到大加入直到图连通。根据M条边权值互不相同可以知道,加进来的这些原边是任意一个方案都必须有的。我们将原边构成的连通块缩成点,显然图最多只有K+1个点。

2.为了保证后面枚举的复杂度,我们要找到能将K+1个点连通起来的最小的K条边,可以发现后面枚举只会使用这K条原边。

3.$O(2^K)$枚举K条边并加入图中(如果构成环则退出),剩下的将选出的K条原边从小到大加入,建出当前方案下的MST。

4.现在需要确定每条Mr. Greedy的边的权值,根据MST的圈性质可知,边<u,v>的权值肯定不能大于MST上u到v的路径中原边的最大值,依次暴力确定即可。

时间复杂度$O(m\alpha(m)+K^22^K)$,理论上可能并不能过。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=l; i<=r; i++)
 4 typedef long long ll;
 5 using namespace std;
 6 
 7 const int N=100010,M=300010,inf=1000000000;
 8 int n,m,K,tot,tmp,cnt,rt,x,d[N],to[110],nxt[110],c[35],f[N],h[N],fa[2][N];
 9 ll sz[N],val[N],ans;
10 struct E{ int x,y,z; bool operator <(const E &a)const{ return z<a.z; }; }a[M],b[35];
11 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
12 int get(int k,int x){ return (fa[k][x]==x) ? x : fa[k][x]=get(k,fa[k][x]); }
13 void uni(int k,int x,int y){ int u=get(k,x),v=get(k,y); if (u!=v) fa[k][u]=v; }
14 
15 void dfs(int x){
16     sz[x]=val[x];
17     for (int i=h[x],k; i; i=nxt[i])
18         if ((k=to[i])!=fa[1][x])
19             fa[1][k]=x,d[k]=d[x]+1,dfs(k),sz[x]+=sz[k];
20 }
21 
22 int main(){
23     freopen("bzoj3206.in","r",stdin);
24     freopen("bzoj3206.out","w",stdout);
25     scanf("%d%d%d",&n,&m,&K);
26     rep(i,1,m) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
27     sort(a+1,a+m+1);
28     rep(i,1,n) fa[0][i]=fa[1][i]=i;
29     rep(i,1,K) scanf("%d%d",&b[i].x,&b[i].y),uni(0,b[i].x,b[i].y);
30     rep(i,1,m){
31         int u=get(0,a[i].x),v=get(0,a[i].y);
32         if (u!=v) fa[0][u]=v,uni(1,a[i].x,a[i].y);
33     }
34     rt=get(1,1);
35     rep(i,1,n) if (get(1,i)==i) c[++tot]=i;
36     rep(i,1,n) scanf("%d",&x),val[get(1,i)]+=x;
37     rep(i,1,m) a[i].x=get(1,a[i].x),a[i].y=get(1,a[i].y);
38     rep(i,1,K) b[i].x=get(1,b[i].x),b[i].y=get(1,b[i].y);
39     rep(i,1,m){
40         int u=get(1,a[i].x),v=get(1,a[i].y);
41         if (u!=v) a[++tmp]=a[i],fa[1][u]=v;
42     }
43     for (int S=0; S<1<<K; S++){
44         bool flag=0; cnt=0;
45         rep(i,1,tot) fa[1][c[i]]=h[c[i]]=0,f[c[i]]=inf,fa[0][c[i]]=c[i];
46         rep(i,1,K) if (S&(1<<(i-1))){
47             int u=get(0,b[i].x),v=get(0,b[i].y);
48             if (u==v) { flag=1; break; } fa[0][u]=v;
49             add(b[i].x,b[i].y); add(b[i].y,b[i].x);
50         }
51         if (flag) continue;
52         rep(i,1,K){
53             int u=get(0,a[i].x),v=get(0,a[i].y);
54             if (u!=v) fa[0][u]=v,add(a[i].x,a[i].y),add(a[i].y,a[i].x);
55         }
56         dfs(rt);
57         rep(i,1,K){
58             int u=a[i].x,v=a[i].y;
59             if (d[u]<d[v]) swap(u,v);
60             for (; d[u]!=d[v]; u=fa[1][u]) f[u]=min(f[u],a[i].z);
61             for (; u!=v; u=fa[1][u],v=fa[1][v]) f[u]=min(f[u],a[i].z),f[v]=min(f[v],a[i].z);
62         }
63         ll tmp=0;
64         rep(i,1,K) if (S&(1<<(i-1))){
65             int u=b[i].x,v=b[i].y;
66             if (d[u]<d[v]) swap(u,v);
67             tmp+=sz[u]*f[u];
68         }
69         ans=max(ans,tmp);
70     }
71     printf("%lld\n",ans);
72     return 0;
73 }

 

posted @ 2018-04-23 17:53  HocRiser  阅读(297)  评论(0编辑  收藏  举报