hdu3491 最小割

Thieves

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


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
  
  
1 5 5 1 5 1 6 6 11 1 1 2 1 3 2 4 3 4 4 5
 

Sample Output
  
  
11
 

Source
 

Recommend
zhouzeyong
 
把一个点拆成2个点 x x'  之间距离为点的权值 注意起点,汇点与各自的所拆点拆点,为inf;
具体见代码
#include <iostream>
#include <cstring>
#include <cstdio>
#define inf 99999999
using namespace std;
struct node
{
    int u,v,f;
};
node e[800000];
int first[3000],next[800000],cc;
int gap[3000],d[3000],curedge[3000],pre[3000];
int sap(int s,int t)
{
    int cur_flow,flow_ans=0,u,tmp,neck,i;
    memset(d,0,sizeof(d));
    memset(gap,0,sizeof(gap));
    memset(pre,-1,sizeof(pre));
    gap[0]=t+1;
    for(i=0;i<=t;i++)
        curedge[i]=first[i];
    u=s;
    while(d[s]<t+1)
    {
        if(u==t)
        {
            cur_flow=inf;
            for(i=s;i!=t;i=e[curedge[i]].v)
            {
                if(cur_flow>e[curedge[i]].f)
                {
                    neck=i;
                    cur_flow=e[curedge[i]].f;
                }
            }
            for(i=s;i!=t;i=e[curedge[i]].v)
            {
                tmp=curedge[i];
                e[tmp].f-=cur_flow;
                e[tmp^1].f+=cur_flow;
            }
            flow_ans+=cur_flow;
            u=neck;
        }
        for(i=curedge[u];i!=-1;i=next[i])
            if(e[i].f&&d[e[i].u]==d[e[i].v]+1)
                break;
        if(i!=-1)
        {
            curedge[u]=i;
            pre[e[i].v]=u;
            u=e[i].v;
        }
        else
        {
            if(0==--gap[d[u]])
                break;
            curedge[u]=first[u];
            for(tmp=t+5,i=first[u];i!=-1;i=next[i])
                if(e[i].f)
                    tmp=min(d[e[i].v],tmp);
            d[u]=tmp+1;
            ++gap[d[u]];
            if(u!=s)
                u=pre[u];
        }
    }
    return flow_ans;
}
inline void add_edge(int u,int v,int f)
{
    e[cc].u=u;
    e[cc].v=v;
    e[cc].f=f;
    next[cc]=first[u];
    first[u]=cc;
    cc++;

    e[cc].v=u;
    e[cc].u=v;
    e[cc].f=0;
    next[cc]=first[v];
    first[v]=cc;
    cc++;
}
int main()
{
    int tt,cas=1;
    scanf("%d",&tt);
    for(cas=1;cas<=tt;cas++)
    {
        int n,m,S,T;
        memset(first,-1,sizeof(first));
        memset(next,-1,sizeof(next));
        cc=0;
        scanf("%d%d%d%d",&n,&m,&S,&T);
        int i;
        for(i=1;i<=n;i++)
        {
            int temp;
            scanf("%d",&temp);
            if(i==S||i==T)
                add_edge(i,i+n,inf);
            else
                add_edge(i,i+n,temp);
        }
        for(i=0;i<m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add_edge(u+n,v,inf);
            add_edge(v+n,u,inf);
        }
        int s=0;
        int t=n*2+1;
        add_edge(s,S,inf);
        add_edge(T,t,inf);
        int ans=sap(s,t);
        printf("%d\n",ans);

    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值