参考: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]道路费用【最小生成树+并查集】的更多相关文章

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

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

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

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

  3. CSP 201703-4 地铁修建【最小生成树+并查集】

    问题描述 试题编号: 201703-4 试题名称: 地铁修建 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 A市有n个交通枢纽,其中1号和n号非常重要,为了加强运输能力,A市 ...

  4. UVA 1395 苗条的生成树(最小生成树+并查集)

    苗条的生成树 紫书P358 这题最后坑了我20分钟,怎么想都对了啊,为什么就wa了呢,最后才发现,是并查集的编号搞错了. 题目编号从1开始,我并查集编号从0开始 = = 图论这种题真的要记住啊!!题目 ...

  5. BZOJ 4569 [Scoi2016]萌萌哒 | ST表 并查集

    传送门 BZOJ 4569 题解 ST表和并查集是我认为最优雅(其实是最好写--)的两个数据结构. 然鹅!他俩加一起的这道题,我却--没有做出来-- 咳咳. 正解是这样的: 类似ST表有\(\log ...

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

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

  7. bzoj 3559: [Ctsc2014]图的分割【最小生成树+并查集】

    读题两小时系列-- 在读懂题意之后,发现M(c)就是c这块最大权割边也就是的最小生成树的最大权边的权值,所以整个问题都可以在MST的过程中解决(M和c都是跟着并查集变的) 不过不是真的最小生成树,是合 ...

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

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

  9. 关于最小生成树(并查集)prime和kruskal

    适合对并查集有一定理解的人.  新手可能看不懂吧.... 并查集简单点说就是将相关的2个数字联系起来 比如 房子                      1   2    3   4  5   6 ...

随机推荐

  1. Django学习之 - 基础视图函数

    视图:Views 获取用户请求的方法: 1: request.GET 2: request.POST 3: request.FILES # checkbox 等多选文件 4:request.POST. ...

  2. csu - 1659 Graph Center(最短路)

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1659 题意是找一个图的中心,图的中心定义是某一个点到其他点的最大距离最小,如果有多个排序输出. 注 ...

  3. http 连接失败重连机制

    1.我们做web开发时,需要经常使用httpclient来请求http服务,有时为了安全起见,服务提供方会提供多个http地址,这样如果我们请求某个ip出现异常,可以重试其他的ip地址,来尽量保证系统 ...

  4. [正在学习开发板]分享--- iTOP-4412移植CAN

    首先拷贝迅为提供的 libcanjni.tar.gz 压缩包到 android 源代码的"iTop4412_ICS/device/samsung/common"文件夹以下,然后使用 ...

  5. 《The Swift Programming Language》的笔记-第27页

    页 1 type safelanguage 本页的主要内容是说swift语言是"类型检查"的安全型编程语言.意思是赋值语句的左值和右值的类型要一致,左值声明是string型变量那么 ...

  6. spring实战笔记6---springMVC的请求过程

    之前有一次在面试其中被问到了这个问题.当时说得不是非常清楚,有些细节的地方想不起来了.所以在这里从新回想和总结一下SpringMVC的起步.请求的运行过程. 在SpringMVC其中.跟请求(Requ ...

  7. Eclipse:Some sites could not be found. See the error log for more detail.解决的方法

    今天遇到了一个奇葩的问题.我把我的sdk tools的版本号升级到23后.我在eclipse中尝试升级ADT,发现了这么一个问题,以下分析下原因: 当我在eclipse中选择Help-->Che ...

  8. C语言的结构体和 C++结构体的区别

     C语言的结构体和 C++结构体的区别 关于C++中声明结构体中需要使用构造器创建实例对象的语法: <C++的结构体构造方法的基本概念:结构体的构造方法需要和结构体的名字相同,并且无返回值,也不 ...

  9. Restrictions.or多个条件用法

    两个条件或查询: Restrictions.or(Restrictions.in("username",list1),Restrictions.idEq(1)); 三个或多个条件查 ...

  10. 20170212-备份ABAP程序

    把生产机上所有后续开发的CBO程序都备份下来.以备急用! 用过2种方法:1.写BDC程序,模拟 TCODE:SE38 -->Program --> Utilities(M)-->Mo ...