HDU-3491-Thieves(拆点 最小割模板)

时间:2019-02-17
本文章向大家介绍HDU-3491-Thieves(拆点 最小割模板),主要包括HDU-3491-Thieves(拆点 最小割模板)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目
在亨利王国,有N个(2 <= N <= 100)个城市,其中M个(M <= 10000)有两条直接连接它们的路。一群来自国外的小偷计划偷走H市的大都会博物馆(它还没有被拆除)。然而,勇敢、聪明、聪明的王国警察早就知道这个计划,他们也计划抓小偷。小偷目前在城里。警察在从S到h的路上试图抓住他们,虽然小偷可能不止一群人走这条路,我们优秀的警察已经收集了I市(1<=I<=N)逮捕小偷所需人数的统计数据。警察不想在S市或H市遇到小偷。警察以最少的人数完成了这项任务。你知道确切的数字吗?

输入

第一行包含一个整数T (T <= 10),表示测试用例的数量。
每个测试用例的第一行有四个整数:N,城市的数量;M为道路数;S (1<=S<=N),城市S的标签;H(1 < = T < = N,S≠H),城市的标签。
第二行包含N个整数,表示每个城市所需的人数。这N个整数的和小于10000。
接下来是M行,每一行包含两个整数x和y,表示x市和y市之间有两条直路,注意S市和H市之间没有路。
每个测试用例之后都有一行空白。

输出

对于每个测试用例,在单独的行中输出一个整数,表示警察使用的最小人数。
Sample Input

1
5 5 1 5
1 6 6 11 1
1 2
1 3
2 4
3 4
4 5

Sample Output

11

拆点
不能在s,t抓小偷,代表s,ss 与 t,tt这两条边不可割, s t 市的警察不可用 但定要联通 故连接为INF的边
( i ,ii , i 地需要的警察)… (s,ss,INF) … (t,tt,INF)
a,b两地相连 (bb,a,INF) (aa,b,INF)

#include <queue>
#include <cstring>
#include <cstdio>
#include <iostream>
#define  m(a,b) memset(a,b,sizeof a)
using namespace std;
typedef long long ll;
const int N=205;
const int M=10000+5;
const int INF=0x3f3f3f3f;
struct Edge{int to,len,nex;}edge[M*4+N*2];
int head[N],d[N];
int tot,s,t,n,m;
void add(int from,int to,int len)
{
    edge[++tot]=(Edge){to,len,head[from]};head[from]=tot;
    edge[++tot]=(Edge){from,0,head[to]};head[to]=tot;
}
queue<int>q;
bool bfs()
{
    while(!q.empty())
        q.pop();
    m(d,0);
    q.push(s);
    d[s]=1;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        for(int i=head[x];i;i=edge[i].nex)
        {
            int y=edge[i].to,l=edge[i].len;
            if(!d[y]&&l)
            {
                d[y]=d[x]+1;
                q.push(y);
                if(y==t)
                    return 1;
            }
        }
    }
    return 0;
}
int dinic(int x,int flow)
{
    if(x==t)
        return flow;
    int res=flow,k;
    for(int i=head[x];i&&res;i=edge[i].nex)
    {
        int y=edge[i].to,l=edge[i].len;
        if(l&&d[y]==d[x]+1)
        {
            k=dinic(y,min(res,l));
            if(!k)
            {
                d[y]=0;
                continue;
            }
            edge[i].len-=k;
            edge[i^1].len+=k;
            res-=k;
        }
    }
    return flow-res;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        m(head,0);
        tot=1;
        scanf("%d%d%d%d",&n,&m,&s,&t);
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            if(i!=s&&i!=t)
                add(i,i+n,x);
            else
                add(i,i+n,INF);
        }
        t+=n;
        while(m--)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            add(a+n,b,INF);
            add(b+n,a,INF);
        }
        ll maxflow=0;
        while(bfs())
            maxflow+=dinic(s,INF);
        printf("%lld\n",maxflow);
    }
}