[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,maxm=60233;
 7 struct zs{
 8     int too,pre,flow;
 9 }e[maxm<<1];int tot,last[maxn];
10 short dis[maxn],dl[maxn];
11 int st[maxn],top,dfn[maxn],low[maxn],tim,bel[maxn],cnt;
12 bool ins[maxn];
13 int i,j,k,n,m,s,t;
14
15 int ra;char rx;
16 inline int read(){
17     rx=getchar(),ra=0;
18     while(rx<‘0‘||rx>‘9‘)rx=getchar();
19     while(rx>=‘0‘&&rx<=‘9‘)ra*=10,ra+=rx-48,rx=getchar();return ra;
20 }
21 inline bool bfs(){
22     memset(dis,0,(n+1)<<1);
23     int l=0,r=1,i,now;dl[1]=s,dis[s]=1;
24     while(l<r&&!dis[t])
25         for(i=last[now=dl[++l]];i;i=e[i].pre)if(e[i].flow&&!dis[e[i].too])
26             dl[++r]=e[i].too,dis[e[i].too]=dis[now]+1;
27     return dis[t];
28 }
29 inline int min(int a,int b){return a<b?a:b;}
30 int dfs(int x,int mx){
31     if(x==t)return mx;
32     int i,used=0,w;
33     for(i=last[x];i;i=e[i].pre)if(e[i].flow&&dis[e[i].too]==dis[x]+1){
34         w=dfs(e[i].too,min(e[i].flow,mx-used));if(w){
35             e[i].flow-=w,e[i^1].flow+=w,used+=w;
36             if(used==mx)return mx;
37         }
38     }
39     dis[x]=0;return used;
40 }
41
42 void tarjan(int x){
43     int i;
44     dfn[x]=low[x]=++tim,ins[x]=1,st[++top]=x;
45     for(i=last[x];i;i=e[i].pre)if(e[i].flow){
46         if(!dfn[e[i].too])tarjan(e[i].too),low[x]=min(low[x],low[e[i].too]);
47         else if(ins[e[i].too])low[x]=min(low[x],dfn[e[i].too]);
48     }
49     if(low[x]==dfn[x]){
50         cnt++;
51         while(st[top]!=x)bel[st[top]]=cnt,ins[st[top]]=0,top--;
52         bel[x]=cnt,ins[x]=0,top--;
53     }
54 }
55
56 inline void insert(int a,int b,int c){
57     e[++tot].too=b,e[tot].flow=c,e[tot].pre=last[a],last[a]=tot,
58     e[++tot].too=a,e[tot].flow=0,e[tot].pre=last[b],last[b]=tot;
59 }
60
61 int main(){
62     n=read(),m=read(),s=read(),t=read(),tot=1;
63     for(i=1;i<=m;i++)j=read(),k=read(),insert(j,k,read());
64     while(bfs())dfs(s,1002333333);
65     for(i=1;i<=n;i++)if(!dfn[i])tarjan(i);
66     for(i=2;i<=tot;i+=2){
67         if(e[i].flow){puts("0 0");continue;}
68         if(bel[e[i^1].too]!=bel[e[i].too])printf("1 ");else printf("0 ");
69         if(bel[e[i^1].too]==bel[s]&&bel[e[i].too]==bel[t])puts("1");else puts("0");
70     }
71     return 0;
72 }
73 

时间: 2024-10-21 19:09:41

[bzoj1797] [Ahoi2009]Mincut 最小割的相关文章

【最小割】【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国想找出一个路径切断方案

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 最小割

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国想找出一个路径切断

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 #incl

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

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

HYSBZ 1797 Mincut 最小割

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

AHOI2009最小割

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

最小割学习小结

一直对最小割模型的理解不够深刻,这段时间学习.总结了一下. [强烈推荐胡伯涛和彭天翼的论文] 总结几点: (1)跑完一遍S-T最大流后,在最小割[S,T]中的边必定都是满流的边,但满流的边不一定都是最小割中的边. (2)最小割的任意方案:跑一遍S-T最大流,然后在残余网络中S能够达到的点为一个割集,剩下的点为另一个割集. (3)最小割方案的唯一性:跑一遍S-T最大流,如果在残余网络中任意一个点都能从S或者T出发达到,那么最小割方案有唯一性:否则没有唯一性. (4)跑一遍S-T最大流后,残余网络中