bzoj 1797: [Ahoi2009]Mincut 最小割

求最小割的可行边与必须边,先求一遍最大流,然后在残量网络上求强连通分量,对于可行边 起始点与结束点要在不同的强连通分量里,对于必须边 起始点要与S在一个SCC里 结束点要与T在一个SCC里。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<cmath>
  6 #include<queue>
  7 #include<algorithm>
  8 #include<vector>
  9 #define M 1000009
 10 #define EPS 1e-10
 11 #define MO 10000
 12 #define ll long long
 13 using namespace std;
 14 ll read()
 15 {
 16     char ch=getchar();
 17     ll x=0,f=1;
 18     for(;ch<‘0‘||ch>‘9‘;ch=getchar())
 19         if(ch==‘-‘)
 20           f=-1;
 21     for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar())
 22         x=x*10+ch-‘0‘;
 23     return x*f;
 24 }
 25 int dfn[M],low[M],T1,belong[M],sum,t,q[M],n,m,S,T,head[M],next[M],u[M],v[M],cnt=1,d[M],f[M],fr[M];
 26 void jia(int a1,int a2,int a3)
 27 {
 28   cnt++;
 29   fr[cnt]=a1;
 30   next[cnt]=head[a1];
 31   head[a1]=cnt;
 32   u[cnt]=a2;
 33   v[cnt]=a3;
 34 }
 35 bool bfs()
 36 {
 37   memset(d,0,sizeof(int)*(n+1));
 38   d[S]=1;
 39   q[1]=S;
 40   int h=0,t=1;
 41   for(;h<t;)
 42     {
 43       int p=q[++h];
 44       for(int i=head[p];i;i=next[i])
 45         if(v[i]&&!d[u[i]])
 46           {
 47             d[u[i]]=d[p]+1;
 48             if(u[i]==T)
 49               return 1;
 50             q[++t]=u[i];
 51           }
 52     }
 53    return 0;
 54 }
 55 int dinic(int x,int f)
 56 {
 57   if(x==T)
 58     return f;
 59   int rest=f;
 60   for(int i=head[x];i&&rest;i=next[i])
 61     if(v[i]&&d[u[i]]==d[x]+1)
 62       {
 63         int now=dinic(u[i],min(rest,v[i]));
 64         if(!now)
 65           d[u[i]]=0;
 66         rest-=now;
 67         v[i]-=now;
 68         v[i^1]+=now;
 69       }
 70   return f-rest;
 71 }
 72 void tarjin(int x)
 73 {
 74   dfn[x]=low[x]=++T1;
 75   q[++t]=x;
 76   f[x]=1;
 77   for(int i=head[x];i;i=next[i])
 78     if(v[i])
 79       {
 80         if(!dfn[u[i]])
 81           {
 82             tarjin(u[i]);
 83             low[x]=min(low[x],low[u[i]]);
 84           }
 85         else  if(f[u[i]])
 86           low[x]=min(low[x],dfn[u[i]]);
 87       }
 88   if(dfn[x]==low[x])
 89     {
 90       sum++;
 91       for(;q[t]!=x;t--)
 92         {
 93           belong[q[t]]=sum;
 94           f[q[t]]=0;
 95         }
 96       belong[x]=sum;
 97       f[x]=0;
 98       t--;
 99     }
100 }
101 int main()
102 {
103    n=read();
104    m=read();
105    S=read();
106    T=read();
107    for(int i=1;i<=m;i++)
108      {
109        int a1=read(),a2=read(),a3=read();
110        jia(a1,a2,a3);
111        jia(a2,a1,0);
112      }
113    for(;bfs();)
114      dinic(S,0x7fffffff);
115    for(int i=1;i<=n;i++)
116      if(!dfn[i])
117        tarjin(i);
118    for(int i=2;i<=cnt;i+=2)
119      if(v[i])
120        printf("0 0\n");
121      else
122        {
123          if(belong[fr[i]]==belong[u[i]])
124            printf("0 ");
125          else
126            printf("1 ");
127          if(belong[fr[i]]==belong[S]&&belong[u[i]]==belong[T])
128            printf("1\n");
129          else
130            printf("0\n");
131        }
132    return 0;
133 }
134 
时间: 2024-10-13 21:34:53

bzoj 1797: [Ahoi2009]Mincut 最小割的相关文章

BZOJ 1797: [Ahoi2009]Mincut 最小割( 网络流 )

先跑网络流, 然后在残余网络tarjan缩点. 考虑一条边(u,v): 当且仅当scc[u] != scc[v], (u,v)可能出现在最小割中...然而我并不会证明 当且仅当scc[u] = scc[S] && scc[v] == scc[T], (u, v) 必定出现在最小割中. 这个很好脑补, 假如这条边不是满流, 那么S-T就存在增广路了.. ----------------------------------------------------------------------

bzoj 1797: [Ahoi2009]Mincut 最小割【tarjan+最小割】

先跑一遍最大流,然后对残量网络(即所有没有满流的边)进行tarjan缩点. 能成为最小割的边一定满流:因为最小割不可能割一半的边: 连接s.t所在联通块的满流边一定在最小割里:如果不割掉这条边的话,就能再次从s到t增广 连接两个不同联通块的满流边可能在最小割里:新图(即缩点后只有满流边的图)的任意一条s.t割都是最小割,所以可以任取割的方案 #include<iostream> #include<cstdio> #include<cstring> #include<

【BZOJ 1797】 [Ahoi2009]Mincut 最小割

1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1244  Solved: 512 [Submit][Status][Discuss] Description A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci.现在B国想找出一个路径切断

[bzoj1797] [Ahoi2009]Mincut 最小割

问最小割中可能成为割边和一定会成为割边的边有哪些. 膜了半天各路题解. 比较详细的解释: http://blog.csdn.net/horizon_smz/article/details/50889806 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=4023,m

【最小割】【Dinic】【强联通分量缩点】bzoj1797 [Ahoi2009]Mincut 最小割

结论: 满足条件一:当一条边的起点和终点不在 残量网络的 一个强联通分量中.且满流. 满足条件二:当一条边的起点和终点分别在 S 和 T 的强联通分量中.且满流.. 网上题解很多的. 1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 #define IN

【BZOJ-1797】Mincut 最小割 最大流 + Tarjan + 缩点

1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1685  Solved: 724[Submit][Status][Discuss] Description A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci.现在B国想找出一个路径切断方案

HYSBZ 1797 Mincut 最小割

Descrption A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci.现在B国想找出一个路径切断方案,使中转站s不能到达中转站t,并且切断路径的代价之和最小. 小可可一眼就看出,这是一个求最小割的问题.但爱思考的小可可并不局限于此.现在他对每条单向道路提出两个问题: 问题一:是否存在一个最小代价路径切断方案,其中该道路被切断? 问题二:

bzoj 1497 最大获利 - 最小割

新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU集团旗下的CS&T通讯公司在新一代通讯技术血战的前夜,需要做太多的准备工作,仅就站址选择一项,就需要完成前期市场研究.站址勘测.最优化等项目.在前期市场调查和站址勘测之后,公司得到了一共N个可以作为通讯信号中转站的地址,而由于这些地址的地理位置差异,在不同的地方建造通讯中转站需要投入的成本也是不一样的,所幸在前期调查之后这些都是已知数据:建立第i个通讯中转站需要的成本为Pi(1≤i≤N).另外公司调查得出了所有期望中的

[BZOJ 2127] happiness 【最小割】

题目链接:BZOJ - 2127 题目分析 首先,每个人要么学文科,要么学理科,所以可以想到是一个最小割模型. 我们就确定一个人如果和 S 相连就是学文,如果和 T 相连就是学理. 那么我们再来确定建图.首先使用最小割,就是先加上所有可能获得的权值,再减去最小割(即不能获得的权值). 如果一个人学理,就要割掉与 S 相连的边,那么就是要割掉学文的收益.于是,对于每个点,从 S 向它连边,权值为它学文的收益. 同理,对于每个点,从它向 T 连边,权值为它学理的收益. 对于两个相邻的人,他们有同时学