Uva 11248 网络扩容

题目链接:https://vjudge.net/contest/144904#problem/A

题意:给定一个有向网络,每条边均有一个容量。问是否存在一个从点1到点N,流量为C的流。如果不存在,是否可以恰好修改一条弧的容量,使得存在这样的流?

分析:

首先找到最大流,如果发现大于等于C,就得到解,如果小于C的话,枚举最小割。这时,之前的最大流保存下来,清空流量,改变最小割的容量,再求最大流。

include <bits/stdc++.h>
using namespace std;

const int maxn = 100 + 10;
const int INF = 0x3f3f3f3f;

struct Edge {
    int from,to,cap,flow;
};

bool operator < (const Edge& a,const Edge& b) {
    return a.from < b.from || (a.from==b.from&&a.to<b.to);
}

struct Dinic {
    int n,m,s,t;
    vector<Edge> edges;
    vector<int> G[maxn];
    bool vis[maxn];
    int d[maxn];
    int cur[maxn];

    void init(int n) {
        for(int i=0;i<n;i++)
            G[i].clear();
        edges.clear();
    }

    void ClearFlow() {
        for(int i=0;i<edges.size();i++) {
            edges[i].flow = 0;
        }
    }

    void AddEdge(int from,int to,int cap) {
        edges.push_back((Edge){from,to,cap,0});
        edges.push_back((Edge){to,from,0,0});
        m = edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }

    bool BFS() {
        memset(vis,0,sizeof(vis));
        queue<int> Q;
        Q.push(s);
        vis[s] = 1;
        d[s] = 0;
        while(!Q.empty()) {
            int x = Q.front();
            Q.pop();
            for(int i=0;i<G[x].size();i++) {
                Edge& e = edges[G[x][i]];
                if(!vis[e.to]&&e.cap>e.flow) {
                    vis[e.to] = 1;
                    d[e.to] = d[x] + 1;
                    Q.push(e.to);
                }
            }
        }
        return vis[t];
    }


    int DFS(int x,int a) {
        if(x==t||a==0) return a;
        int flow =0,f;
        for(int& i=cur[x];i<G[x].size();i++) {
            Edge& e = edges[G[x][i]];
            if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0) {
                e.flow +=f;
                edges[G[x][i]^1].flow -=f;
                flow +=f;
                a-=f;
                if(a==0) break;
            }
        }
        return flow;
    }

    int Maxflow(int s,int t) {
        this->s = s;
        this->t = t;
        int flow = 0;
        while(BFS()) {
            memset(cur,0,sizeof(cur));
            flow +=DFS(s,INF);
        }
        return flow;
    }

    vector<int> Mincut() {
        vector<int> ans;
        for(int i=0;i<edges.size();i++) {
            Edge& e = edges[i];
            if(vis[e.from]&&!vis[e.to]&&e.cap>0)
                ans.push_back(i);
        }
        return ans;
    }


    void Reduce () {
        for(int i=0;i<edges.size();i++)
            edges[i].cap -=edges[i].flow;
    }

};

Dinic g;

int main()
{
    int kase = 1;
    int n,e,c;
    while(scanf("%d%d%d",&n,&e,&c)==3&&n) {
        g.init(n);
        for(int i=0;i<e;i++) {
            int u,v,cap;
            scanf("%d%d%d",&u,&v,&cap);
            u--;v--;
            g.AddEdge(u,v,cap);
        }
        printf("Case %d: ",kase ++);
        int flow = g.Maxflow(0,n-1);
        if(flow>=c) printf("possible
");

        else {
            vector<int> cut = g.Mincut();
            g.Reduce();
            vector<Edge> ans;
            for(int i=0;i<cut.size();i++) {
                Edge& e = g.edges[cut[i]];
                int temp = e.cap;   ///
                e.cap = c;
                g.ClearFlow();
                if(flow+g.Maxflow(0,n-1)>=c)
                    ans.push_back(e);
                e.cap = temp;       ///
            }
            if(ans.empty())
                printf("not possible
");
            else {
                sort(ans.begin(),ans.end());
                printf("possible option:(%d,%d)",ans[0].from+1,ans[0].to + 1);
                for(int i=1;i<ans.size();i++) {
                    printf(",(%d,%d)",ans[i].from+1,ans[i].to+1);
                }
                puts("");
            }
        }
    }



    return 0;
}
原文地址:https://www.cnblogs.com/TreeDream/p/6160144.html