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)$,理论上可能并不能过。

 #include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
typedef long long ll;
using namespace std; const int N=,M=,inf=;
int n,m,K,tot,tmp,cnt,rt,x,d[N],to[],nxt[],c[],f[N],h[N],fa[][N];
ll sz[N],val[N],ans;
struct E{ int x,y,z; bool operator <(const E &a)const{ return z<a.z; }; }a[M],b[];
void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
int get(int k,int x){ return (fa[k][x]==x) ? x : fa[k][x]=get(k,fa[k][x]); }
void uni(int k,int x,int y){ int u=get(k,x),v=get(k,y); if (u!=v) fa[k][u]=v; } void dfs(int x){
sz[x]=val[x];
for (int i=h[x],k; i; i=nxt[i])
if ((k=to[i])!=fa[][x])
fa[][k]=x,d[k]=d[x]+,dfs(k),sz[x]+=sz[k];
} int main(){
freopen("bzoj3206.in","r",stdin);
freopen("bzoj3206.out","w",stdout);
scanf("%d%d%d",&n,&m,&K);
rep(i,,m) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
sort(a+,a+m+);
rep(i,,n) fa[][i]=fa[][i]=i;
rep(i,,K) scanf("%d%d",&b[i].x,&b[i].y),uni(,b[i].x,b[i].y);
rep(i,,m){
int u=get(,a[i].x),v=get(,a[i].y);
if (u!=v) fa[][u]=v,uni(,a[i].x,a[i].y);
}
rt=get(,);
rep(i,,n) if (get(,i)==i) c[++tot]=i;
rep(i,,n) scanf("%d",&x),val[get(,i)]+=x;
rep(i,,m) a[i].x=get(,a[i].x),a[i].y=get(,a[i].y);
rep(i,,K) b[i].x=get(,b[i].x),b[i].y=get(,b[i].y);
rep(i,,m){
int u=get(,a[i].x),v=get(,a[i].y);
if (u!=v) a[++tmp]=a[i],fa[][u]=v;
}
for (int S=; S<<<K; S++){
bool flag=; cnt=;
rep(i,,tot) fa[][c[i]]=h[c[i]]=,f[c[i]]=inf,fa[][c[i]]=c[i];
rep(i,,K) if (S&(<<(i-))){
int u=get(,b[i].x),v=get(,b[i].y);
if (u==v) { flag=; break; } fa[][u]=v;
add(b[i].x,b[i].y); add(b[i].y,b[i].x);
}
if (flag) continue;
rep(i,,K){
int u=get(,a[i].x),v=get(,a[i].y);
if (u!=v) fa[][u]=v,add(a[i].x,a[i].y),add(a[i].y,a[i].x);
}
dfs(rt);
rep(i,,K){
int u=a[i].x,v=a[i].y;
if (d[u]<d[v]) swap(u,v);
for (; d[u]!=d[v]; u=fa[][u]) f[u]=min(f[u],a[i].z);
for (; u!=v; u=fa[][u],v=fa[][v]) f[u]=min(f[u],a[i].z),f[v]=min(f[v],a[i].z);
}
ll tmp=;
rep(i,,K) if (S&(<<(i-))){
int u=b[i].x,v=b[i].y;
if (d[u]<d[v]) swap(u,v);
tmp+=sz[u]*f[u];
}
ans=max(ans,tmp);
}
printf("%lld\n",ans);
return ;
}

[BZOJ3206][APIO2013]道路费用(最小生成树)的更多相关文章

  1. [Bzoj3206][Apio2013]道路费用(kruscal)(缩点)

    3206: [Apio2013]道路费用 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 536  Solved: 252[Submit][Status ...

  2. BZOJ3206 [Apio2013]道路费用

    首先我们强制要求几条待定价的边在MST中,建出MST 我们发现这个MST中原来的边是一定要被选上的,所以可以把点缩起来,搞成一棵只有$K$个点的树 然后$2^K$枚举每条边在不在最终的MST中,让在最 ...

  3. 洛谷P3639 [APIO2013] 道路费用 [生成树的特殊算法]

    题目传送门 道路费用 格式难调,题面就不放了. 分析: 这是一道要细(yan)心(jing)的生成树的好(gui)题. 首先我们看到$k$的范围非常小,那么我们就可以直接$2^k$枚举每一条加边是否选 ...

  4. bzoj 3206: [Apio2013]道路费用【最小生成树+并查集】

    参考:http://hzwer.com/6888.html 把k条道路权值设为0,和其他边一起跑MST,然后把此时选中的其他边设为必选,在新图中加上必选变缩成k个点,把所有边重标号,枚举k跳边的选取情 ...

  5. [APIO2013]道路费用

    题目描述 幸福国度可以用 N 个城镇(用 1 到 N 编号)构成的集合来描述,这些城镇 最开始由 M 条双向道路(用 1 到 M 编号)连接.城镇 1 是中央城镇.保证一个 人从城镇 1 出发,经过这 ...

  6. 题解 [APIO2013]道路费用

    link Description 幸福国度可以用 N 个城镇(用 1 到 N 编号)构成的集合来描述,这些城镇 最开始由 M 条双向道路(用 1 到 M 编号)连接.城镇 1 是中央城镇.保证一个 人 ...

  7. 题解 洛谷 P3639 【[APIO2013]道路费用 】

    不难想到可以\(2^k\)去枚举\(k\)条新边的选择方案,然后加入原图中的边来使图连通,用当前方案的收益去更新答案,但是这样复杂度过不去. 可以先把\(k\)条新边都连上,然后再加入边权从小到大排序 ...

  8. bzoj 1626: [Usaco2007 Dec]Building Roads 修建道路【最小生成树】

    先把已有的边并查集了,然后MST即可 记得开double #include<iostream> #include<cstdio> #include<algorithm&g ...

  9. PKUSC2018训练日程(4.18~5.30)

    (总计:共66题) 4.18~4.25:19题 4.26~5.2:17题 5.3~5.9: 6题 5.10~5.16: 6题 5.17~5.23: 9题 5.24~5.30: 9题 4.18 [BZO ...

随机推荐

  1. IOI1998 Polygon [区间dp]

    [IOI1998]Polygon 题意翻译 题目可能有些许修改,但大意一致 多边形是一个玩家在一个有n个顶点的多边形上的游戏,如图所示,其中n=4.每个顶点用整数标记,每个边用符号+(加)或符号*(乘 ...

  2. Linux重定向: > 和 &> 区别

    总结:>只能将正常信息重定向 &>可以将错误信息或者普通信息都重定向输出(下面是实测) [root@Dev_yang shellScript]# lll -bash: lll: c ...

  3. Nim博弈(nim游戏)

    http://blog.csdn.net/qiankun1993/article/details/6765688 NIM 游戏 重点结论:对于一个Nim游戏的局面(a1,a2,...,an),它是P- ...

  4. JVM内存模型 二

    在并发编程中,多个线程之间采取什么机制进行通信(信息交换),什么机制进行数据的同步? 在Java语言中,采用的是共享内存模型来实现多线程之间的信息交换和数据同步的. 线程之间通过共享程序公共的状态,通 ...

  5. bzoj 1604: [Usaco2008 Open]Cow Neighborhoods 奶牛的邻居——排序+贪心+set

    Description 了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000)只奶牛,你会发现她们已经结成了几个“群”.每只奶牛在吃草的时候有一个独一无二的位置坐标Xi,Yi(l ...

  6. python 写 excel 模块 : xlwt

    主要来自:[ python中使用xlrd.xlwt操作excel表格详解 ] 为了方便阅读, 我将原文两个模块拆分为两篇博文: [ python 读 excel 模块: xlrd ] [ python ...

  7. Intellij IDEA创建spring MVC项目

    相信各位未来的Java工程师已经接触到了spring MVC这个框架的强大之处,看了很多的教程,都是eclipse的,在intellij IDEA这个强大的工具面前居然不能很顺畅的,今天我就带领大家用 ...

  8. ie6浏览器兼容性

    1.ie6双倍边距bug 块状元素设置float(左浮动或有浮动),并且设置margin值之后,第一个浮动的元素其左侧margin值为正常的2倍,如图,可以看到第一个元素的左侧边距于其他元素两两之间的 ...

  9. 160多条Windows 7 “运行”命令

    160多条Windows 7 “运行”命令: 删除或更改应用程序 = control appwiz.cpl 添加设备 = devicepairingwizard  蓝牙文件传输 = fsquirt  ...

  10. POJ1080(LCS变形)

    Human Gene Functions Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Oth ...