网络流(三)----最大流SAP算法

以  HDU 3572  Task Schedule 为例的模板

Code:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>

using namespace std;

const int inf = 0x3f;
const int INF = 0x3f3f3f3f;
const int maxn = 40002;

struct Node
{
    int to, flow, next;
}edge[maxn * 8];

int n, m;
int S, T;
int tot;

int q[maxn];
int dis[maxn], pre[maxn], rec[maxn], head[maxn];
int gap[maxn], cur[maxn];

inline void Add_edge(int a, int b, int c)
{
    edge[tot].to = b; edge[tot].flow = c; edge[tot].next = head[a];
    head[a] = tot++;
    edge[tot].to = a; edge[tot].flow = 0; edge[tot].next = head[b];
    head[b] = tot++;
}

void Init()
{
    tot = 0; 
    memset(head, -1, sizeof(head));
}

void BFS()
{
    int i; 
    int h = 0, t = 0;
    for(i = 0; i <= T; i++) dis[i] = INF;
    q[h] = T;
    dis[T] = 0;
    while(h <= t)
    {
        int u = q[h++];
        gap[dis[u]]++;
        for(i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if(dis[v] == INF && edge[i^1].flow)
            {
                dis[v] = dis[u] + 1;
                q[++t] = v;
            }
        }
    }
}

int SAP()
{
    int i;
    int u = pre[S] = S, Maxflow = 0, flow = INF;

    for(i = 0; i <= T; i++)//这里 T 为最大顶点编号
    {
        gap[i] = 0;
        cur[i] = head[i];
    }
    BFS();
    while(dis[S] <= T)
    {
        if(u == T)
        {
            Maxflow += flow;
            for(; u != S; u = pre[u])
            {
                edge[rec[u]].flow -= flow;
                edge[rec[u]^1].flow += flow;
            }
            flow = INF;
        }

        for(i = cur[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if(edge[i].flow && dis[u] == dis[v] + 1)
            {
                flow = min(flow, edge[i].flow);
                pre[v] = u;
                rec[v] = i;
                cur[u] = i;//当前弧优化
                u = v;
                break;
            }
        }
        if(i == -1)
        {
            int mindis = T + 1;//T是顶点数
            if((--gap[dis[u]]) == 0) break;//间隙优化
            for(i = cur[u] = head[u]; i != -1; i = edge[i].next)
            {
                if(edge[i].flow && mindis > dis[edge[i].to])
                {
                    mindis = dis[edge[i].to];
                }
            }
            gap[dis[u] = mindis+1]++;
            u = pre[u];
        }
    }
    return Maxflow;
}
int main()
{
    int ncase,n,m;
    scanf("%d",&ncase);
    for(int kase = 1;kase <= ncase;kase++){
        Init();
        scanf("%d%d",&n,&m);
        S = 0,T = 1001;
        int sum = 0;
        for(int i = 1;i <= n;i++){
            int start,process,end;
            scanf("%d%d%d",&process,&start,&end);
            sum += process;
            Add_edge(S,i,process);
            for(int j = start;j <= end;j++)
                Add_edge(i,500+j,1);
        }
        for(int i = 501;i <= 1000;i++)
            Add_edge(i,T,m);
        bool flag = true;
        int tmp = SAP();
        //printf("tmp = %d
",tmp);
        if(tmp != sum)  flag = false;
        printf("Case %d: ",kase);
        if(flag)    printf("Yes

");
        else        printf("No

");
    }
    return 0;
}