参考: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. Swift--字典的了解

    字典存储时,key和value值的类型都是固定的,且都是无序的. 1.字典类型的缩写语法 在swift中,字典的完整格式如下: Dictionary<Key, Value> 注意:字典的k ...

  2. Segments--poj3304(判断直线与线段之间的关系)

    http://poj.org/problem?id=3304 给你几条线段  然后 让你找到一条直线让他在这条直线上的映射有一个重合点 如果有这条直线的话  这个重合的部分的两个端点一定是某两条线段的 ...

  3. CodeForces 429B【dp】

    题意: 在一个n*m的矩阵中有两只虫子,一只从左上角向右下角移动,另外一只从左下角向右上角移动. 要求: 1.第一只虫子每次只能向左或者向下移动一格,另外一只只能向上或者向右移动一格. 2.两只虫子的 ...

  4. Spring MVC表单实例

    以下内容引用自http://wiki.jikexueyuan.com/project/spring/mvc-framework/spring-mvc-form-handling-example.htm ...

  5. c++之虚基类初始化

    C++虚基类构造函数下面文章详细介绍C++虚基,所谓C++虚基类:是由最派生类的构造函数通过调用虚基类的构造函数进行初始化的,但前提是要深入理解到底什么是C++虚基类,及他是怎么运行的. 前面讲过,为 ...

  6. socket的bind函数是不是只能绑定本地IP,不能绑定外网IP么?

    参考: https://bbs.csdn.net/topics/391024376 别瞎猜测. 所谓bind,就是指绑定本地接受端口. 指定ip,是为了分辨多ip主机. --------------- ...

  7. Linux 下使用 Sar 简介

    Linux 下使用 Sar 简介 提交 我的留言 加载中 已留言 介绍 Sar 最早是实现在 Salaris Unix 系统里,后来移植到了大部分其他的 Unix 系统(如AIX,HP-UX等).Li ...

  8. 报错** is not accessible due to restriction on required library

    报错: Description Resource Path Location TypeAccess restriction: The type Map<String,Object> is ...

  9. 对dispatch_async到主线程的逻辑封装成C/C++接口类型

    背景:代码里面有时候会把将要运行的内容放到主线程里面运行,但假设已经是主线程里面的代码调用dispatch_async的时候偶尔会出现crash,所以就须要推断是否已经在主线程里面了. 通常的做法类似 ...

  10. HBase单机环境搭建

    在搭建HBase单机环境之前,首先你要保证你已经搭建好Java环境: $ java -version java version "1.8.0_51" Java(TM) SE Run ...