HDU 3987 Harry Potter and the Forbidden Forest (求割边最少的最小割)

来源:互联网 发布:骚男的辣条淘宝店网址 编辑:程序博客网 时间:2024/05/01 00:16

此题与POJ3204值得对比一下,POJ3204是求割边,既关键边的数量,每一条关键边都会影响到最小割。而此题是求满足最小割的情况下,割边最要最少,求出最少的割边数量。做法是先跑一遍最大流,得到残留网络,对与该网络,如果流量为0(满流)则将流量改为1,否则改为无穷大,再跑一次最大流就得到答案---最少割边数。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#define SIZE 1024using namespace std;typedef __int64 Int;const Int inf = (Int)1<<60;struct node{    int to,next;    Int val;}edge[SIZE*512];node cp[SIZE*512];int Case,N,M,sc,sk,pt;Int ret;int head[SIZE],idx;int gap[SIZE],dis[SIZE];void addnode(int from,int to,Int val){    edge[idx].to = to;    edge[idx].val = val;    edge[idx].next = head[from];    head[from] = idx++;    edge[idx].to = from;    edge[idx].val = 0;    edge[idx].next = head[to];    head[to] = idx++;}int dfs(int cur,Int cval){    if(cur == sk)        return cval;    int mindis = pt-1;    Int tval = cval;    for(int i=head[cur]; i!=-1; i=edge[i].next)    {        int to = edge[i].to;        if(edge[i].val > 0)        {            if(dis[to] + 1 == dis[cur])            {                Int val = dfs(to,min(edge[i].val,tval));                tval -= val;                edge[i].val -= val;                edge[i^1].val += val;                if(dis[sc] >= pt)                    return cval-tval;                if(!tval)                    break;            }            if(mindis > dis[to])                mindis = dis[to];        }    }    if(cval == tval)    {        --gap[dis[cur]];        if(!gap[dis[cur]])            dis[sc] = pt;        dis[cur] = mindis + 1;        ++gap[dis[cur]];    }    return cval - tval;}void sap(){    memset(gap,0,sizeof(gap));    memset(dis,0,sizeof(dis));    ret = 0;    gap[sc] = pt;    while(dis[sc] < pt)        ret += dfs(sc,inf);}void read(){    scanf("%d%d",&N,&M);    sc = 0, sk = N-1, pt = sk+1;    idx = 0;    memset(head,-1,sizeof(head));    int s,e,d;    Int v;    for(int i=1; i<=M; i++)    {        scanf("%d%d%I64d%d",&s,&e,&v,&d);        addnode(s,e,v);        if(d)            addnode(e,s,v);    }}void work(){    for(int i=0; i<idx; i++)    {        cp[i].to = edge[i].to;        cp[i].val = edge[i].val;        cp[i].next = edge[i].next;    }    int index = idx;    idx = 0;    memset(head,-1,sizeof(head));    for(int i=0; i<index; i+=2)    {        if(cp[i].val == 0) addnode(cp[i^1].to,cp[i].to,1);        else addnode(cp[i^1].to,cp[i].to,inf);    }    sap();    printf("%I64d\n",ret);}int main(){    scanf("%d",&Case);    for(int ca = 1; ca <= Case; ca ++)    {        read();        sap();        printf("Case %d: ",ca);        work();    }    return 0;}