bzoj 3206: [Apio2013]道路费用【最小生成树+并查集】
参考:http://hzwer.com/6888.html
把k条道路权值设为0,和其他边一起跑MST,然后把此时选中的其他边设为必选,在新图中加上必选变缩成k个点,把所有边重标号,枚举k跳边的选取情况,和其他边做MST,建出树,k条边的权值在树上取min
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=300005,inf=1e9;
int n,m,k,top,cnt,s,f[N],fa[N],p[N],po[N],de[N],h[N],mn[N];
long long va[N],sum[N],ans;
bool mk[N];
struct qwe
{
int ne,to;
}e[N];
struct bian
{
int u,v,w;
}a[N],b[25],q[N];
bool cmp(const bian &a,const bian &b)
{
return a.w<b.w;
}
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
inline void add(int u,int v)
{
cnt++;
e[cnt].ne=h[u];
e[cnt].to=v;
h[u]=cnt;
}
inline void ins(int u,int v)
{
add(u,v);
add(v,u);
}
inline int zhao(int x)
{
return x==fa[x]?x:fa[x]=zhao(fa[x]);
}
inline int zh(int x)
{
return x==f[x]?x:f[x]=zh(f[x]);
}
void dp(int u)
{
sum[u]=va[u];
for(int i=h[u];i;i=e[i].ne)
if(e[i].to!=f[u])
{
de[e[i].to]=de[u]+1;
f[e[i].to]=u;
dp(e[i].to);
sum[u]+=sum[e[i].to];
}
}
void wk()
{
cnt=0;
for(int i=1;i<=k+1;i++)
{
int p=po[i];
h[p]=f[p]=0;
fa[p]=p,mn[p]=inf;
}
for(int i=1;i<=k;i++)
if(mk[i])
{
int fu=zhao(b[i].u),fv=zhao(b[i].v);
if(fu==fv)
return;
fa[fu]=fv;
ins(b[i].u,b[i].v);
}
for(int i=1;i<=k;i++)
{
int fu=zhao(q[i].u),fv=zhao(q[i].v);
if(fu!=fv)
{
fa[fu]=fv;
ins(q[i].u,q[i].v);
}
}
dp(s);
for(int i=1;i<=k;i++)
{
int u=q[i].u,v=q[i].v;
if(de[u]>de[v])
swap(u,v);
while(de[u]!=de[v])
mn[v]=min(mn[v],q[i].w),v=f[v];
while(u!=v)
{
mn[v]=min(mn[v],q[i].w);
mn[u]=min(mn[u],q[i].w);
u=f[u],v=f[v];
}
}
long long con=0;
for(int i=1;i<=k;i++)
if(mk[i])
{
int u=b[i].u,v=b[i].v;
if(de[u]>de[v])
swap(u,v);
con+=mn[v]*sum[v];
}
ans=max(ans,con);
}
void dfs(int x)
{
if(x==k+1)
{
wk();
return;
}
mk[x]=0;
dfs(x+1);
mk[x]=1;
dfs(x+1);
}
int main()
{
n=read(),m=read(),k=read();
for(int i=1;i<=m;i++)
a[i].u=read(),a[i].v=read(),a[i].w=read();
sort(a+1,a+1+m,cmp);
for(int i=1;i<=k;i++)
b[i].u=read(),b[i].v=read();
for(int i=1;i<=n;i++)
p[i]=read();
for(int i=1;i<=n;i++)
fa[i]=f[i]=i;
for(int i=1;i<=k;i++)
fa[zhao(b[i].u)]=zhao(b[i].v);
for(int i=1;i<=m;i++)
{
int u=a[i].u,v=a[i].v;
if(zhao(u)!=zhao(v))
{
fa[zhao(u)]=fa[zhao(v)];
f[zh(u)]=f[zh(v)];
}
}
s=zh(1);
for(int i=1;i<=n;i++)
{
int z=zh(i);
va[z]+=p[i];
if(z==i)
po[++po[0]]=i;
}
for(int i=1;i<=k;i++)
b[i].u=zh(b[i].u),b[i].v=zh(b[i].v);
for(int i=1;i<=m;i++)
a[i].u=zh(a[i].u),a[i].v=zh(a[i].v);
for(int i=1;i<=m;i++)
{
int fu=zh(a[i].u),fv=zh(a[i].v);
if(fu!=fv)
mk[i]=1,f[fu]=fv;
}
for(int i=1;i<=m;i++)
if(mk[i])
q[++top]=a[i];
dfs(1);
printf("%lld\n",ans);
return 0;
}
bzoj 3206: [Apio2013]道路费用【最小生成树+并查集】的更多相关文章
- [BZOJ3206][APIO2013]道路费用(最小生成树)
3206: [Apio2013]道路费用 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 568 Solved: 266[Submit][Status ...
- [Bzoj3206][Apio2013]道路费用(kruscal)(缩点)
3206: [Apio2013]道路费用 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 536 Solved: 252[Submit][Status ...
- CSP 201703-4 地铁修建【最小生成树+并查集】
问题描述 试题编号: 201703-4 试题名称: 地铁修建 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 A市有n个交通枢纽,其中1号和n号非常重要,为了加强运输能力,A市 ...
- UVA 1395 苗条的生成树(最小生成树+并查集)
苗条的生成树 紫书P358 这题最后坑了我20分钟,怎么想都对了啊,为什么就wa了呢,最后才发现,是并查集的编号搞错了. 题目编号从1开始,我并查集编号从0开始 = = 图论这种题真的要记住啊!!题目 ...
- BZOJ 4569 [Scoi2016]萌萌哒 | ST表 并查集
传送门 BZOJ 4569 题解 ST表和并查集是我认为最优雅(其实是最好写--)的两个数据结构. 然鹅!他俩加一起的这道题,我却--没有做出来-- 咳咳. 正解是这样的: 类似ST表有\(\log ...
- 洛谷P3639 [APIO2013] 道路费用 [生成树的特殊算法]
题目传送门 道路费用 格式难调,题面就不放了. 分析: 这是一道要细(yan)心(jing)的生成树的好(gui)题. 首先我们看到$k$的范围非常小,那么我们就可以直接$2^k$枚举每一条加边是否选 ...
- bzoj 3559: [Ctsc2014]图的分割【最小生成树+并查集】
读题两小时系列-- 在读懂题意之后,发现M(c)就是c这块最大权割边也就是的最小生成树的最大权边的权值,所以整个问题都可以在MST的过程中解决(M和c都是跟着并查集变的) 不过不是真的最小生成树,是合 ...
- 题解 洛谷 P3639 【[APIO2013]道路费用 】
不难想到可以\(2^k\)去枚举\(k\)条新边的选择方案,然后加入原图中的边来使图连通,用当前方案的收益去更新答案,但是这样复杂度过不去. 可以先把\(k\)条新边都连上,然后再加入边权从小到大排序 ...
- 关于最小生成树(并查集)prime和kruskal
适合对并查集有一定理解的人. 新手可能看不懂吧.... 并查集简单点说就是将相关的2个数字联系起来 比如 房子 1 2 3 4 5 6 ...
随机推荐
- Match the string--hdu1797(模拟)
http://acm.hdu.edu.cn/showproblem.php?pid=1797 就是模拟 我的思路是标记aba 和h的位置 然后就判断是否正确 就行了 还有就是 最后 fkfkfkf ...
- 寒武纪camp Day4
补题进度:7/11 A(博弈论) 略 B 待填坑 C(贪心) 题意: 一个序列是good的当且仅当相邻两个数字不相同.给出一个长度为n的数列,每个数字是ai.定义一种操作就是把a中某个元素拿到首位去, ...
- BCD工具类(8421)
目录 1.BCD介绍 (1)BCD码(Binary-Coded Decimal)亦称二进码十进数.用4位二进制数来表示1位十进制数中的0~9这10个数码.用二进制编码的十进制代码. (2)BCD码可分 ...
- SQL Server Fundamentals
http://www.cnblogs.com/CreateMyself/category/810461.html
- 使用Spring定时任务并且通过AOP监控任务执行情况
原文:http://www.open-open.com/code/view/1426250803279 本文讲的是通过Spring注解的方式实现任务调度.只要引入了spring-context包就能够 ...
- Mysql不同存储引擎的表转换方法
Mysql不同存储引擎的表转换方法 1.Alter table直接修改表的存储引擎,但是这样会导致大量的系统开销,Mysql为此要执行一个就表向新表的逐行复制.在此期间,转换操作可能会占用服务器的所有 ...
- Office WORD如何为每一页设置不同的页眉页脚
如下图所示,我想要为封面和目录,摘要等等设置不同的页眉页脚(一般封面和目录不需要页脚) 而从正文开始,套用相同的页眉和以页数作为页脚(注意"第一章 绪论"不是这个文档的第一页) ...
- OpenCV---在图片上加入文字
/****************************************** func:cvText desc:put text on an image @param img The ima ...
- C#趣味程序---百鸡百钱
问题:公鸡一仅仅5元,母鸡一仅仅3元,小鸡三仅仅1元.问100元能够买多少仅仅鸡? using System; namespace ConsoleApplication1 { class Progra ...
- System.Diagnostics.Debug.WriteLine 在OutPut中无输出
TextWriterTraceListener writer = new TextWriterTraceListener(System.Console.Out); Debug ...