zoukankan      html  css  js  c++  java
  • 【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;
    }
  • 相关阅读:
    安装和使用git遇到的问题总结
    继承时,构造函数和析构函数的调用顺序
    c++文件的读写
    虚函数
    纯虚函数
    继承
    连接到github
    NDK无法包含std的头文件(string,list等)的解决方法
    Centos7.3安装maven并配置加速镜像源
    分享几个实用好看的WordPress主题(第二波)
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11287616.html
Copyright © 2011-2022 走看看