HDU 3491 Thieves 拆点 最小割

来源:互联网 发布:matlab分水岭算法 编辑:程序博客网 时间:2024/05/11 01:46

题意:警察抓小偷,已知每个城市至少需要的警察人数,警察要在s到h的路上抓到全部小偷,求最少需要的警察人数

分析:求最小割,等于最大流,把每个城市拆成2个点,一个点入,一个点出,2点之间的容量为这个城市的警察人数,相连的城市加容量为INF的边,求最大流




#include <iostream>#include<cstdio>#include<string>#include<cstring>#include<algorithm>#define MAXN 205#define MAXE 50000#define INF 0x7fffffffusing namespace std;struct Edge{    int to,from,cap,next;}edge[MAXE];int head[MAXN],cnt,n,m,src,des;int dep[MAXN],gap[MAXN];void init(){    memset(head,-1,sizeof(head));    cnt=0;}void addedge(int cu,int cv,int cw){  // cout<<cu<<' '<<cv<<' '<<cw<<endl;    edge[cnt].from=cu;edge[cnt].to=cv;edge[cnt].cap=cw;edge[cnt].next=head[cu];head[cu]=cnt++;    edge[cnt].from=cv;edge[cnt].to=cu;edge[cnt].cap=0;edge[cnt].next=head[cv];head[cv]=cnt++;}int que[MAXN];void BFS(){    memset(dep,-1,sizeof(dep));    memset(gap,0,sizeof(gap));    gap[0]=1;    int L=0,R=0;    dep[des]=0;    que[R++]=des;    int u,v;    while(L!=R){        u=que[L++];        L=L%MAXN;        for(int i=head[u];i!=-1;i=edge[i].next){            v=edge[i].to;            if(edge[i^1].cap==0||dep[v]!=-1)            continue;            que[R++]=v;            R=R%MAXN;            ++gap[dep[v]=dep[u]+1];        }    }}int cur[MAXN],stack[MAXN];int Sap(){    int res=0;    BFS();    int top=0;    memcpy(cur,head,sizeof(head));    int u=src,i;    while(dep[src]<n){        if(u==des){            int temp=INF,inser=n;            for(i=0;i!=top;++i){                if(temp>edge[stack[i]].cap){                    temp=edge[stack[i]].cap;                    inser=i;                }            }            for(i=0;i!=top;++i){                edge[stack[i]].cap-=temp;                edge[stack[i]^1].cap+=temp;            }            res+=temp;            top=inser;            u=edge[stack[top]].from;        }        for(i=cur[u];i!=-1;i=edge[i].next)        if(edge[i].cap!=0&&dep[u]==dep[edge[i].to]+1)        break;        if(i!=-1){            cur[u]=i;            stack[top++]=i;            u=edge[i].to;        }else{            if(--gap[dep[u]]==0)            break;            int minn=n;            for(i=head[u];i!=-1;i=edge[i].next){                if(edge[i].cap==0)                continue;                if(minn>dep[edge[i].to]){                    minn=dep[edge[i].to];                    cur[u]=i;                }            }            ++gap[dep[u]=minn+1];            if(u!=src)            u=edge[stack[--top]].from;        }    }    return res;}int main(){    int t,s,h,i,u,v,ans;    scanf("%d",&t);    while(t--){        init();        scanf("%d%d%d%d",&n,&m,&s,&h);        for(i=1;i<=n;i++){            scanf("%d",&u);            addedge(i,i+n,u);            addedge(i+n,i,u);        }        src=s+n;        des=h;        while(m--){            scanf("%d%d",&u,&v);            addedge(u+n,v,INF);            addedge(v+n,u,INF);        }        n*=2;        ans=Sap();        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击