BZOJ 2521 最小生成树(最小割)

http://www.lydsy.com/JudgeOnline/problem.php?id=2521

题意:每次能增加一条边的权值1,求最小代价让一条边保证在最小生成树里

思路:如果两个点中有环,那么这条边必须不能是环的最大边,这样子把之前所有的边权值变成V+1-v[i],无向图网络流就可以了

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 #define inf 0x7fffffff
 7 struct edge{
 8     int u,v,w;
 9 }e[200005];
10 int n,m,id,dis[200005],cnt[200005],tot,S,T,nodes;
11 int flow[200005],op[200005],next[200005],first[200005],go[200005];
12 int read(){
13     char ch=getchar();int t=0,f=1;
14     while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘) f=-1;ch=getchar();}
15     while (‘0‘<=ch&&ch<=‘9‘){t=t*10+ch-‘0‘;ch=getchar();}
16     return t*f;
17 }
18 void insert(int x,int y,int z){
19     tot++;
20     go[tot]=y;
21     next[tot]=first[x];
22     first[x]=tot;
23     flow[tot]=z;
24 }
25 void add(int x,int y,int z){
26     insert(x,y,z);op[tot]=tot+1;
27     insert(y,x,0);op[tot]=tot-1;
28 }
29 void add2(int x,int y,int z){
30     insert(x,y,z);op[tot]=tot+1;
31     insert(y,x,z);op[tot]=tot-1;
32 }
33 int dfs(int x,int f){
34     if (x==T) return f;
35     int mn=nodes,sum=0;
36     for (int i=first[x];i;i=next[i]){
37         int pur=go[i];
38         if (flow[i]&&dis[pur]+1==dis[x]){
39             int save=dfs(pur,std::min(f-sum,flow[i]));
40             sum+=save;
41             flow[i]-=save;
42             flow[op[i]]+=save;
43             if (sum==f||dis[S]>=nodes) return sum;
44         }
45         if (flow[i]) mn=std::min(mn,dis[pur]);
46     }
47     if (sum==0){
48         cnt[dis[x]]--;
49         if (cnt[dis[x]]==0){
50             dis[S]=nodes;
51         }else{
52             dis[x]=mn+1;
53             cnt[dis[x]]++;
54         }
55     }
56     return sum;
57 }
58 int main(){
59     n=read();m=read();id=read();
60     S=0,T=n+1;nodes=n+2;
61     for (int i=1;i<=m;i++){
62         e[i].u=read();e[i].v=read();e[i].w=read();
63     }
64     add(S,e[id].u,inf);
65     add(e[id].v,T,inf);
66     for (int i=1;i<=m;i++)if (i!=id&&e[i].w<=e[id].w){
67         add2(e[i].u,e[i].v,e[id].w+1-e[i].w);
68     }
69     int ans=0;
70     while (dis[S]<nodes) ans+=dfs(S,inf);
71     printf("%d\n",ans);
72 }
时间: 2024-08-06 11:09:20

BZOJ 2521 最小生成树(最小割)的相关文章

BZOJ 2561: 最小生成树(最小割)

U,V能在最小(大)生成树上,当且仅当权值比它小(大)的边无法连通U,V. 两次最小割就OK了. --------------------------------------------------------------------- #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<vector> #include<que

【BZOJ-2521】最小生成树 最小割

2521: [Shoi2010]最小生成树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 415  Solved: 242[Submit][Status][Discuss] Description Secsa最近对最小生成树问题特别感兴趣.他已经知道如果要去求出一个n个点.m条边的无向图的最小生成树有一个Krustal算法和另一个Prim的算法.另外,他还知道,某一个图可能有多种不同的最小生成树.例如,下面图 3中所示的都是图 2中的无向图的最小

【BZOJ2521】[Shoi2010]最小生成树 最小割

[BZOJ2521][Shoi2010]最小生成树 Description Secsa最近对最小生成树问题特别感兴趣.他已经知道如果要去求出一个n个点.m条边的无向图的最小生成树有一个Krustal算法和另一个Prim的算法.另外,他还知道,某一个图可能有多种不同的最小生成树.例如,下面图 3中所示的都是图 2中的无向图的最小生成树: 当然啦,这些都不是今天需要你解决的问题.Secsa想知道对于某一条无向图中的边AB,至少需要多少代价可以保证AB边在这个无向图的最小生成树中.为了使得AB边一定在

BZOJ 2127: happiness( 最小割 )

最小割.. S连每个人(容量:选择理科的愉悦):每个人连T(容量:选择理科的愉悦) . 对于每一组(x, y, w)x和y同选理增加的愉悦w,新建节点V,V连x(INF),V连y(INF), S连V(w) 对于每一组(x, y, w)x和y同选文增加的愉悦w,新建节点V,x连V(INF),y连V(INF), V连T(w) ------------------------------------------------------------------- #include<cstdio> #i

BZOJ 2229 ZJOI2011 最小割 最小割+分治 400AC达成&amp;&amp;2000Submission达成

题目大意:给定一个图,多次询问有多少个点对之间的最小割小于等于某个值 最小割分治- - 首先朴素的想法是做O(n^2)遍网络流 但是这样显然是过不去的 根据一些结论,最小割最多有n-1个,这n-1个最小割构成一个最小割树 别问我为什么- - 因此我们分治寻找这n-1个最小割 每层分治,先任选两个点作为源汇做一遍最小割 然后找出S集和T集,对所有S集的点和T集的点构成的点对用本次得到的最小割更新一遍 注意更新的是全部S集和全部T集,不只是本次分治内部的S集和T集 然后将本次分治的点分成S集和T集,

[BZOJ 1797][AHOI2009]最小割(最小割关键边的判断)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1797 分析: 在残余网络中看: 对于第1问: 1.首先这个边必须是满流 2.其次这个边连接的两个点U,V必须属于两个SCC,即这个边必须为一个割 对于第2问: 在第1问的基础上,还要判断U和S.V和T是否分别在同一个SCC中,如果成立,那么这样才是必须的.

bzoj 3144 切糕 —— 最小割

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3144 每个点拆成 R 个,连成一条链,边上是权值,割掉代表选这一层: 然后每个点的第 t 层向四周的点的第 t-d 层连边,就能达到选了第 i 条边,则四周的点必须选 i-d ~ T 范围的边,而对方反过来一连,就限制在 i-d ~ i+d 了: 竟然因为忘记 ct=1 而调了一小时呵呵... 代码如下: #include<cstdio> #include<cstring>

BZOJ 2127: happiness(最小割解决集合划分)

Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 2350  Solved: 1138[Submit][Status][Discuss] Description 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值.作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的

BZOJ 3275: Number( 最小割 )

--------------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 3009; const int INF = 0x7FFFFFFF; struct edge { int to, cap; edge *next, *rev; } E[1000000], *p