nyist 677 网络流

#include <queue>
#include <stdio.h>
#include <string.h>
#include<iostream>
using namespace std;
#define N 1005
#define M 400005
#define INF 0x7fffffff
#define min(a,b) a < b ?  a : b
#define CLR(a,v) memset(a,v,sizeof(a))
struct Vertex
{
    int head;
}V[N];
struct Edge
{
    int v,c,f,next;
    Edge(){}
    Edge(int v,int c,int f,int ne):v(v),c(c),f(f),next(ne){}
}E[M];
int d[N],pre[N],cur[N],gap[N];
int top,s,t,n,m,p;
void Init()
{
    top = 0;
    CLR(V,-1);
}
void add(int u,int v,int c)
{
    E[top] = Edge(v,c,0,V[u].head);
    V[u].head = top++;
    E[top] = Edge(u,0,0,V[v].head);
    V[v].head = top++;
}
void set_d()
{
    queue<int> Q;
    CLR(d,-1);
    CLR(gap,0);
    d[t] = 0;
    Q.push(t);
    while(!Q.empty())
    {
        int v = Q.front();
        Q.pop();
        ++gap[ d[v] ];

        for(int i=V[v].head;i!=-1;i=E[i].next)
        {
            int u = E[i].v;

            if(d[u] == -1)
            {
                d[u] = d[v]+1;
                Q.push(u);
            }
        }
    }
}
int Sap()
{
    set_d();                                        //You can replace it with "CLR(d,0)" if you feel it trouble
    int MaxFlow = 0, u = s;
    int flow = INF;
    memcpy(cur,V,sizeof(V));                        //current arc
    while(d[s] <= n)   // 此处小心,标注的问题,因为这道题,构造了一个须有的节点,恰好还是一条链,故改为<=
    {
        int &i = cur[u];                            //reference
        for(;i!=-1;i=E[i].next)
        {
            int v = E[i].v;
            if(E[i].c > E[i].f && d[u] == d[v]+1)  //admissible arc
            {
                u = v;
                pre[v] = i;
                flow = min(flow,E[i].c-E[i].f);
               ;
                if(u == t)
                {
                    while(u != s)
                    {
                        int j = pre[u];
                        E[j].f   += flow;
                        E[j^1].f -= flow;
                        u = E[j^1].v;
                    }
                   // cout<<flow<<endl;
                    MaxFlow += flow;

                    flow = INF;
                }
                break;
            }
        }
        if(i == -1)                                //there's no admissible arc.
        {
            if(--gap[ d[u] ] == 0)
                break;
            int dmin = n-1;
            cur[u] = V[u].head;
            for(int j=V[u].head;j!=-1;j=E[j].next)
                if(E[j].c > E[j].f)                //not full arc
                    dmin = min(dmin,d[ E[j].v ]);
            d[u] = dmin+1;
            ++gap[ d[u] ];
            if(u != s)
                u = E[ pre[u]^1 ].v;
        }
    }
    return MaxFlow;
}
int a[1000];
int main()
{
    int T;
   //freopen("input.txt","r",stdin);
   //freopen("output.txt","w",stdout);
    scanf("%d",&T);
    int u,v;
    int cas = 1;
    while(T --)
    {
        int w;
        Init();
        scanf("%d%d%d",&n,&m,&p);
        for(int i=0;i<p;i++){
            scanf("%d",&a[i]);
        }
        while(m--)
        {
            scanf("%d%d",&u,&v);
            if(u != v){
            add(u,v,1);
            add(v,u,1);
            }
        }
        int ans = 0;

        for(int i=0;i<p;i++)
        {
            add(203,a[i],INF);
        }

        s = 203;
        t = n;
        printf("Case #%d: %d\n",cas++,Sap());

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值