[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 ...
随机推荐
- mootools框架里如何使用ajax
ajax可通过直接写源码实现,但有点繁琐,现在流行的ajax框架都集成了ajax的功能,而且写起来非常简单方便.当然mootools也不例外.mootools是一个非常优秀的javascript的库, ...
- 第五届华中区程序设计邀请赛暨武汉大学第十四届校赛 网络预选赛 A
Problem 1603 - Minimum Sum Time Limit: 2000MS Memory Limit: 65536KB Total Submit: 564 Accepted: ...
- POJ1062:昂贵的聘礼(dfs)
昂贵的聘礼 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 58108 Accepted: 17536 题目链接:http ...
- SICAU-OJ:要我唱几首歌才能够将你捕捉
要我唱几首歌才能够将你捕捉 题意: 有N种颜色的牛,现在可以执行以下两种操作: 1.抓捕一只牛,代价为ai: 2.花费x的代价使用魔法,让所有颜色加1,N会变为1. 求得到N种颜色的牛最少花费的代价. ...
- rsync 同步
1./usr/bin/rsync -vzrtopg --progress --include "weibo-service-server" --exclude "/*& ...
- PHP代码优化小笔记
1.十万级以上次执行情况,方法可以被静态化,考虑声明为静态.html静态页面速度更快 2.echo 替换print:echo时逗号连接符替换点号连接符 3.循环之前设置循环最大次数,循环参数不要使用函 ...
- django 连接 oracle 问题
安装 oracle 后,在 django 项目中连接出现问题记录. 问题1:pip install cx_Oacle 未出现任何问题,但运行过程出现: 原因:连接 oracle 的工具 cx_Orac ...
- php连接mysql报错——Fatal error: Call to undefined function mysql_connect() in
练习php连接mysql数据库 代码:mysql_connect("127.0.0.1:3306","root", ..... 浏览器报错:Fatal erro ...
- 【BZOJ】[SDOI2009]HH的项链
[算法]主席树||离线+树状数组 [题解] 主席树经典应用:找区间不同的数字个数. 做法:记录每个数上一次出现的位置last[i],对last建权值线段树,对于区间询问last[i]<L的数字个 ...
- HDU 4334 Trouble (数组合并)
Trouble Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...