[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 50Sample Output
400HINT
在样例中, 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
这种题一般不是数据结构+分类讨论,就是缩图。
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]道路费用(最小生成树)的更多相关文章
- [Bzoj3206][Apio2013]道路费用(kruscal)(缩点)
3206: [Apio2013]道路费用 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 536 Solved: 252[Submit][Status ...
- BZOJ3206 [Apio2013]道路费用
首先我们强制要求几条待定价的边在MST中,建出MST 我们发现这个MST中原来的边是一定要被选上的,所以可以把点缩起来,搞成一棵只有$K$个点的树 然后$2^K$枚举每条边在不在最终的MST中,让在最 ...
- 洛谷P3639 [APIO2013] 道路费用 [生成树的特殊算法]
题目传送门 道路费用 格式难调,题面就不放了. 分析: 这是一道要细(yan)心(jing)的生成树的好(gui)题. 首先我们看到$k$的范围非常小,那么我们就可以直接$2^k$枚举每一条加边是否选 ...
- bzoj 3206: [Apio2013]道路费用【最小生成树+并查集】
参考:http://hzwer.com/6888.html 把k条道路权值设为0,和其他边一起跑MST,然后把此时选中的其他边设为必选,在新图中加上必选变缩成k个点,把所有边重标号,枚举k跳边的选取情 ...
- [APIO2013]道路费用
题目描述 幸福国度可以用 N 个城镇(用 1 到 N 编号)构成的集合来描述,这些城镇 最开始由 M 条双向道路(用 1 到 M 编号)连接.城镇 1 是中央城镇.保证一个 人从城镇 1 出发,经过这 ...
- 题解 [APIO2013]道路费用
link Description 幸福国度可以用 N 个城镇(用 1 到 N 编号)构成的集合来描述,这些城镇 最开始由 M 条双向道路(用 1 到 M 编号)连接.城镇 1 是中央城镇.保证一个 人 ...
- 题解 洛谷 P3639 【[APIO2013]道路费用 】
不难想到可以\(2^k\)去枚举\(k\)条新边的选择方案,然后加入原图中的边来使图连通,用当前方案的收益去更新答案,但是这样复杂度过不去. 可以先把\(k\)条新边都连上,然后再加入边权从小到大排序 ...
- bzoj 1626: [Usaco2007 Dec]Building Roads 修建道路【最小生成树】
先把已有的边并查集了,然后MST即可 记得开double #include<iostream> #include<cstdio> #include<algorithm&g ...
- 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 ...
随机推荐
- POJ2253:Frogger(改造Dijkstra)
Frogger Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 64864 Accepted: 20127 题目链接:ht ...
- java注解(Annotation)的简单介绍
注解你可以理解为一个特殊的类,或者接口其自定义个格式形如 public @interface 注解名(){ //注解的属性,特别提醒当注解的属性为value时,在对其赋值时,可以不写value,而直接 ...
- mmall项目之问题一(mavenplugin问题)
在进行mybatis逆向工程到时候,报错,提示maven plugin 错误,提示missing..... 解决办法: 因为之前到pom中忘记了加版本信息,添加后错误消失:
- word使用宏 在文章中插入源代码进行排版
1.宏的代码如下. Sub 设置代码表格() ' author: code4101 ' 设置代码表格 宏 ' ' ' 背景色为morning的配色方案,RGB为(229,229,229) ) With ...
- iBatis之Iterator的使用
一:前言 现在这个项目使用的是iBatis,我刚刚开始的时候说是用MyBatis,因为我以前用过,觉得还是比较好用的啊,而且不像iBatis样,查什么一个字段不能多也不能少,觉得好无语啊. 二:内容 ...
- HDFS的xshell及dfsadmin命令
一. DFS:distributied file system 是一种允许文件通过网络在多台主机上风向的文件系统,可让多机器上的多用户分享文件和存储空间 二.HDFS的shell **切记后面加的 / ...
- HDOJ 3501 Calculation 2
题目链接 分析: 要求的是小于$n$的和$n$不互质的数字之和...那么我们先求出和$n$互质的数字之和,然后减一减就好了... $\sum _{i=1}^{n} i[gcd(i,n)==1]=\le ...
- [bzoj3004][SDOI2012]吊灯——樹形DP
Brief Description 給定一棵樹, 判斷是否可以將其分成\(\frac{n}{k}\)個聯通塊, 其中每個聯通塊的大小均爲k. Algorithm Design 我們有一個結論: k可行 ...
- 【Python实例二】之前期准备:Windows下的BeautifulSoup安装
前言 一直久闻Python的爬虫很高效,而且操作便捷,因此决定开始练习爬虫的相关内容. 首先尝试的是Python的爬虫利器之一:BeautifulSoup.(这名字听起来就有种想要去探究的兴趣.... ...
- web前端 html/css总结点
1.html块级.内联<img src="" alt="图片未加载提示" title="鼠标悬浮提示"><a href=& ...