HDU 3491 Thieves 最小点割集+拆点==最大流(建图可贵)

来源:互联网 发布:万能钥匙mac版 编辑:程序博客网 时间:2024/05/17 21:39

点击打开链接

 

Thieves

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 1047    Accepted Submission(s): 473


Problem Description
In the kingdom of Henryy, there are N (2 <= N <= 100) cities, with M (M <= 10000) two-direct ways connecting them.
A group of thieves from abroad plan to steal the metropolitan museum in city H (It has not been demolished). However, the brave, brilliant, bright police in the kingdom have known this plan long before, and they also plan to catch the thieves. The thieves are in the city S at present. The police try to catch them on their way from S to H. Although the thieves might travel this way by more than one group, our excellent police has already gather the statistics that the number of the people needed in city I (1<=I<=N) to arrest the thieves.
The police do not want to encounter the thieves in either city S or city H.
The police finish the task with the minimum number of people. Do you know the exact number?
 


 

Input
The first line contains an integer T (T <= 10), indicating the number of the test cases.
The first line of each test case has four integers: N, the number of the cities; M, the number of the roads; S (1<=S<=N), the label of city S; H (1<=T<=N, S≠H), the label of city H.
The second line contains N integers, indicating the number of people needed in each city. The sum of these N integers is less than 10000.
Then M lines followed, each containing two integers x and y, indicating that there is a two-direct roads between city x and y. Notices that no road between city S and H.
A blank line is followed after each test case.
 


 

Output
For each test case, output a single integer in a separate line, indicating the minimum number of people the police used.
 


 

Sample Input
15 5 1 51 6 6 11 11 21 32 43 44 5
 


 

Sample Output
11
 


 

Source
2010 ACM-ICPC Multi-University Training Contest(6)——Host by BIT
 


 

Recommend
zhouzeyong

 

 

题意是说一群小偷要从s点到h点,现在有n个点,m条路。现在每个点都有一定的人把守。问你需要多少人才能堵住小偷,使他们不能从s到h点。并且不能在s点或者h点堵截。此题贵在建图。这是一道最小割的题目,根据最小割==最大流定理,建好图之后,求最大流即可。首先要将每个点拆成两个点,权值把守的人数,除了s和h点之外,s到s+n和h到h+n之间的权值为无穷大,两个能够相邻的点之间的权值也为无穷大。

#include<stdio.h>#include<string.h>#define inf 0x3f3f3f3f#define MIN(a,b) a>b?b:a;#define M 1000010struct E{    int v,w,next;    E() {}    E(int v,int w,int next):v(v),w(w),next(next) {}} edg[M];int dis[M],gap[M],list[M],nodes;int sourse,sink,nn,node;void addedge(int u,int v,int w){    edg[nodes]=E(v,w,list[u]);    list[u]=nodes++;    edg[nodes]=E(u,0,list[v]);    list[v]=nodes++;}int dfs(int src,int aug){    if(src==sink)return aug;    int left=aug,mindis=nn;    for(int j=list[src]; j!=-1; j=edg[j].next)    {        int v=edg[j].v;        if(edg[j].w)        {            if(dis[v]+1==dis[src])            {                int minn=MIN(left,edg[j].w);                minn=dfs(v,minn);                edg[j].w-=minn;                edg[j^1].w+=minn;                left-=minn;                if(dis[sourse]>=nn)return aug-left;                if(left==0)break;            }            if(dis[v]<mindis)                mindis=dis[v];        }    }    if(left==aug)    {        if(!(--gap[dis[src]]))dis[sourse]=nn;        dis[src]=mindis+1;        gap[dis[src]]++;    }    return aug-left;}int sap(int s,int e){    int ans=0;    nn=e+1;    memset(dis,0,sizeof(dis));    memset(gap,0,sizeof(gap));    gap[0]=nn;    sourse=s;    sink=e;    while(dis[sourse]<nn)        ans+=dfs(sourse,inf);    return ans;}int main(){    int cas;    scanf("%d",&cas);    while(cas--)    {        int n,m,s,e,h,a,b;        scanf("%d%d%d%d",&n,&m,&s,&h);        memset(list,-1,sizeof(list));        int p,sum=0,maxx=0;        for(int i=1;i<=n;i++)        {            scanf("%d",&a);            if(i!=s&&i!=h)                addedge(i,i+n,a);            else                addedge(i,i+n,inf);        }        for(int i=1;i<=m;i++)        {            scanf("%d%d",&a,&b);            addedge(a+n,b,inf);            addedge(b+n,a,inf);        }        int ee=h+n;        e=2*n+1;        addedge(ee,e,inf);        nodes=0;        sourse=0;        int anss=sap(s,e);        printf("%d\n",anss);    }    return 0;}


 

 

 

 

原创粉丝点击