ACM-ICPC 2018 沈阳赛区网络预赛 F. Fantastic Graph(有源上下界最大流 模板)

关于有源上下界最大流: https://blog.csdn.net/regina8023/article/details/45815023

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n, m, k, l, r, s, t, superS, superT;
const int MAXN = 5000;//点数的最大值
const int MAXM = 120000;//边数的最大值
const int INF = 0x3f3f3f3f;
struct Edge
{
    int to,next,cap,flow;

} edge[MAXM]; //注意是MAXM
int tol;
int head[MAXN];
void init()
{
    tol = 2;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw = 0)
{
    edge[tol].to = v;
    edge[tol].cap = w;
    edge[tol].flow = 0;
    edge[tol].next = head[u];
    head[u] = tol++;
    edge[tol].to = u;
    edge[tol].cap = rw;
    edge[tol].flow = 0;
    edge[tol].next = head[v];
    head[v] = tol++;
}
int Q[MAXN];
int dep[MAXN],cur[MAXN],sta[MAXN];
bool bfs(int s,int t,int n)
{
    int front = 0,tail = 0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s] = 0;
    Q[tail++] = s;
    while(front < tail)
    {
        int u = Q[front++];
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if(edge[i].cap > edge[i].flow && dep[v] == -1)
            {
                dep[v] = dep[u] + 1;
                if(v == t)
                    return true;
                Q[tail++] = v;
            }
        }
    }
    return false;
}
int dinic(int s,int t,int n)
{
    int maxflow = 0;
    while(bfs(s,t,n))
    {
        for(int i = 0; i < n; i++)
            cur[i] = head[i];
        int u = s, tail = 0;
        while(cur[s] != -1)
        {
            if(u == t)
            {
                int tp = INF;
                for(int i = tail-1; i >= 0; i--)
                    tp = min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                maxflow += tp;
                for(int i = tail-1; i >= 0; i--)
                {
                    edge[sta[i]].flow += tp;
                    edge[sta[i]^1].flow -= tp;
                    if(edge[sta[i]].cap-edge[sta[i]].flow == 0)
                        tail = i;
                }

                u = edge[sta[tail]^1].to;
            }
            else if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to])
            {
                sta[tail++] = cur[u];
                u = edge[cur[u]].to;
            }
            else
            {
                while(u != s && cur[u] == -1)
                    u = edge[sta[--tail]^1].to;
                cur[u] = edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}
int main()
{
    int kase = 1;
    while(~scanf("%d %d %d", &m, &n, &k))
    {
        scanf("%d %d", &l,  &r);
        s = n + m + 1;
        t = n + m + 2;
        superS = n + m + 3;
        superT = n + m + 4;
        init();
        for(int i = 1; i <= k; i++)
        {
            int u, v;
            scanf("%d %d", &u , &v);
            addedge(u, v + n, 1); //二分图 建一条容量为1的边
        }
        addedge(t,s,INF); //从汇点向源点建一条inf的边
        for(int i = 1; i <= n; i++){
            addedge(s, i, r - l); //从源点向左半图连边
            addedge(superS, i, l);
            addedge(s, superT, l);
        }
        for(int i = 1; i <= m; i++){
            int aim = i + n;
            addedge(aim, t, r - l);
            addedge(aim, superT, l);
            addedge(superS, t, l);
        }
        printf("Case %d: ", kase++);
        int ans = dinic(superS, superT, n+m+4);
        if(ans == (n+m)*l) puts("Yes");
        else puts("No");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Jadon97/p/9692975.html