bzoj 3206: [Apio2013]道路费用【最小生成树+并查集】
2018-04-18 10:38
561 查看
参考: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 ,fa ,p ,po ,de ,h ,mn ; long long va ,sum ,ans; bool mk ; struct qwe { int ne,to; }e ; struct bian { int u,v,w; }a ,b[25],q ; 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; }
相关文章推荐
- [BZOJ3206][APIO2013]道路费用(最小生成树)
- bzoj 3206: [Apio2013]道路费用 最小生成树
- BZOJ3206 [Apio2013]道路费用
- [Bzoj3206][Apio2013]道路费用(kruscal)(缩点)
- bzoj 3206: [Apio2013]道路费用
- bzoj 3206: [Apio2013]道路费用 dfs+最小生成树+并查集
- bzoj3206 [Apio2013]道路费用
- NKOJ 2784 (APIO 2013) 道路费用(最小生成树+缩点)
- bzoj3206 [Apio2013]道路费用
- 【并查集】【生成树】【APIO 2008】【bzoj 3624】免费道路
- 3206: [Apio2013]道路费用
- BZOJ 3624: [Apio2008]免费道路 [生成树 并查集]
- [BZOJ]3624: [Apio2008]免费道路 最小生成树
- [对偶 KM算法 生成树 || 最大费用可行流 || 线性规划] BZOJ 1937 [Shoi2004]Mst 最小生成树
- 【bzoj3624】[Apio2008]免费道路 贪心+并查集
- 【BZOJ3624】【APIO2008】免费道路(贪心+并查集)
- bzoj 1626: [Usaco2007 Dec]Building Roads 修建道路【最小生成树】
- [BZOJ3624][Apio2008]免费道路(贪心+并查集)
- bzoj 3624: [Apio2008]免费道路 生成树的构造
- 【BZOJ3624】【APIO2008】免费道路 [生成树][贪心]