【AHOI2009】最小割

我大安徽的题~

题面

https://www.luogu.org/problem/P4126

题解

对于一条有向边$(u,v)$

关键割边(一定在最小割上的边)的判定:$u$所在强连通分量和$S$一样,$v$所在强连通分量和$T$一样,并且满流。

性质:容量+1,则最小割/最大流+1。

可能割边(有一种最小割的方案割掉它)的判定:$u$所在强连通分量和$v$不一样,并且满流。

性质:容量-1,则最小割/最大流-1。

#include<stack>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 5050
#define M 60500
#define INF 1000000007
#define ri register int
using namespace std;

int n,m,s,t;
int u[M],v[M],w[M];

struct graph {
  #define S s
  #define T t
  vector<int> ed[N];
  vector<int> w,to;
  int d[N],cur[N];
  int bel[N],dfn[N],low[N],cc,cnt;
  bool ins[N];
  stack<int> stk;
  void add_edge(int u,int v,int tw) {
    to.push_back(v); w.push_back(tw); ed[u].push_back(to.size()-1);
    to.push_back(u); w.push_back(0) ; ed[v].push_back(to.size()-1);
  }
  bool bfs() {
    queue<int> q;
    memset(d,0x3f,sizeof(d));
    d[S]=0; q.push(S);
    while (!q.empty()) {
      int x=q.front(); q.pop();
      for (ri i=0;i<ed[x].size();i++) {
        int e=ed[x][i];
        if (d[x]+1<d[to[e]] && w[e]) {
          d[to[e]]=d[x]+1;
          q.push(to[e]);
        }
      }
    }
    return d[T]<INF;
  }
  int dfs(int x,int limit) {
    if (x==T || limit==0) return limit;
    int sum=0; 
    for (ri &i=cur[x];i<ed[x].size();i++) {
      int e=ed[x][i];
      if (w[e] && d[x]+1==d[to[e]]) {
        int f=dfs(to[e],min(limit,w[e]));
        if (!f) continue;
        sum+=f; limit-=f; 
        w[e]-=f; w[1^e]+=f;
        if (!limit) return sum;
      }
    }
    return sum;
  }
  int dinic() {
    int ret=0;
    while (bfs()) {
      memset(cur,0,sizeof(cur));
      ret+=dfs(S,INF);
    }
    return ret;
  }
  void tarjan(int x) {
    dfn[x]=low[x]=++cc;
    ins[x]=1; stk.push(x);
    for (ri i=0;i<ed[x].size();i++) {
      int e=ed[x][i];
      if (!w[e]) continue;
      if (dfn[to[e]]) {
        if (ins[to[e]]) low[x]=min(low[x],dfn[to[e]]);
      }
      else {
        tarjan(to[e]);
        low[x]=min(low[x],low[to[e]]);
      }
    }
    if (dfn[x]==low[x]) {
      int t; ++cnt;
      do {
        t=stk.top(); stk.pop(); ins[t]=0;
        bel[t]=cnt;
      }
      while (t!=x);
    }
  }
} G;

int main() {
  scanf("%d %d %d %d",&n,&m,&s,&t);
  for (ri i=1;i<=m;i++) {
    scanf("%d %d %d",&u[i],&v[i],&w[i]);
    G.add_edge(u[i],v[i],w[i]);
  }
  G.dinic();
  for (ri i=1;i<=n;i++) if (!G.dfn[i]) G.tarjan(i);
  for (ri i=0;i<G.to.size();i+=2) {
    if (G.bel[G.to[i^1]]!=G.bel[G.to[i]] && !G.w[i]) putchar('1'); else putchar('0');
    putchar(' ');
    if (G.bel[G.to[i^1]]==G.bel[s] && G.bel[G.to[i]]==G.bel[t] && !G.w[i]) putchar('1'); else putchar('0');
    puts("");
  }
  return 0;
}
posted @ 2019-08-02 11:34  HellPix  阅读(237)  评论(0编辑  收藏  举报