bzoj1797 [Ahoi2009]Mincut 最小割

我们首先跑一遍最大流。

可以发现如果一个流没跑或者没有跑满,他肯定不再最小割中。如果没跑,那么去掉它之后新图的最小割依然等于最大流,所以割他没有用,而没有跑满的边可以看作是一个满了的边和一个空的边,割了就是浪费了他多余的流量。

那么如果一个边跑满了呢?

 对于残留网络缩点,如果$id[u]!=id[v]$,那么可能选到这条边。

如果 $id[u]==id[S]且id[v]==id[T]$ ,那么一定选这条边。

现在感性理解了,理性证明坑待填。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <iostream>
  5 #include <cmath>
  6 #include <queue>
  7 #define N 4005
  8 #define inf 0x7fffffff
  9 using namespace std;
 10 int n,m,S,T;
 11 int e=2,head[N];
 12 struct edge{
 13     int u,v,f,next;
 14 }ed[120050];
 15 void add(int u,int v,int f){
 16     ed[e].u=u;ed[e].v=v;ed[e].f=f;
 17     ed[e].next=head[u];head[u]=e++;
 18     ed[e].u=v;ed[e].v=u;ed[e].f=0;
 19     ed[e].next=head[v];head[v]=e++;
 20 }
 21 int dep[N];
 22 bool bfs(){
 23     memset(dep,0,sizeof dep);
 24     queue<int> Q;
 25     Q.push(S);dep[S]=1;
 26     while(!Q.empty()){
 27         int x=Q.front();Q.pop();
 28         for(int i=head[x];i;i=ed[i].next){
 29             if(ed[i].f&&!dep[ed[i].v]){
 30                 dep[ed[i].v]=dep[x]+1;
 31                 if(ed[i].v==T)return 1;
 32                 Q.push(ed[i].v);
 33             }
 34         }
 35     }
 36     return 0;
 37 }
 38 int dfs(int x,int f){
 39     if(x==T||!f)return f;
 40     int ans=0;
 41     for(int i=head[x];i;i=ed[i].next){
 42         if(ed[i].f&&dep[ed[i].v]==dep[x]+1){
 43             int nxt=dfs(ed[i].v,min(f,ed[i].f));
 44             ans+=nxt;f-=nxt;ed[i].f-=nxt;ed[i^1].f+=nxt;
 45         }
 46         if(!f)break;
 47     }
 48     if(!ans)dep[x]=-1;
 49     return ans;
 50 }
 51 int dinic(){
 52     int ans=0;
 53     while(bfs())ans+=dfs(S,inf);
 54     return ans;
 55 }
 56 int dfn[N],low[N],top,q[N],id[N],tot;
 57 bool bo[N];
 58 void tarjan(int x){
 59     dfn[x]=low[x]=++top;
 60     q[top]=x;bo[x]=1;
 61     for(int i=head[x];i;i=ed[i].next){
 62         if(ed[i].f){
 63             int v=ed[i].v;
 64             if(!dfn[v]){
 65                 tarjan(v);
 66                 low[x]=min(low[x],low[v]);
 67             }
 68             else if(bo[v]){
 69                 low[x]=min(low[x],dfn[v]);
 70             }
 71         }
 72     }
 73     if(low[x]==dfn[x]){
 74         int y;tot++;
 75         do{
 76             y=q[top--];
 77             id[y]=tot;
 78             bo[y]=0;
 79         }while(y!=x);
 80     }
 81 }
 82 int main(){
 83     scanf("%d%d%d%d",&n,&m,&S,&T);
 84     for(int i=1,u,v,f;i<=m;i++){
 85         scanf("%d%d%d",&u,&v,&f);
 86         add(u,v,f);
 87     }
 88     dinic();
 89     for(int i=1;i<=n;i++)
 90         if(!dfn[i])tarjan(i);
 91     for(int i=2;i<e;i+=2){
 92         if(!ed[i].f){
 93             if(id[ed[i].u]!=id[ed[i].v])printf("1 ");
 94             else printf("0 ");
 95             if(id[ed[i].u]==id[S]&&id[ed[i].v]==id[T])puts("1");
 96             else puts("0");
 97         }
 98         else puts("0 0");
 99     }
100     return 0;
101 }
View Code

 

posted @ 2018-01-16 11:24  Ren_Ivan  阅读(162)  评论(0编辑  收藏  举报