HDU 4289

来源:互联网 发布:组策略 网络访问 编辑:程序博客网 时间:2024/05/16 19:01
//HDU 4289
//在一个带点权中去掉若干个点使从ds到不了dt
//网络流建图:对所有点进行拆点(包括ds和dt)因为可能在ds,dt就进行拦截
//建图规则:每个点拆成i和i+n;cap(i,i+n)的容量为其点权
//如果i,j连通,则cap(i+n,j)=MAX cap(j+n,i)=MAX;
//新建两个点S,T为源汇点,S到ds有一条容量为MAX的边
//dt+n到T也有一条容量为MAX的边
//此时的最大流就是最小的带权点割集。。。
#include"stdio.h"#include"string"#include"queue"using namespace std;#define MAXE 80001#define MAXV 604#define MAX 99999999typedef struct{int u;int v;int cap;int next;}Edge;Edge edge[MAXE];int head[MAXV];int dis[MAXV];int cur[MAXV];int cost[MAXV];int zhan[MAXV];int s,t;int num;void add(int x,int y,int z){edge[num].u=x;edge[num].v=y;edge[num].cap=z;edge[num].next=head[x];head[x]=num;num++;edge[num].u=y;edge[num].v=x;edge[num].cap=0;edge[num].next=head[y];head[y]=num;num++;}int bfs(){int i;int v=s;queue<int> q;memset(dis,-1,sizeof(dis));dis[v]=0;q.push(v);while(q.empty()==0){v=q.front();q.pop();for(i=head[v];i!=-1;i=edge[i].next){if(dis[edge[i].v]==-1 && edge[i].cap>0 ){dis[edge[i].v]=dis[v]+1;q.push(edge[i].v);}}if(v==t) return 1;}return 0;}int dinic(){int v;int min;int i;int index;int ans=0;int top;while(bfs()){v=s;top=0;memcpy(cur,head,sizeof(head));while(top>=0){if(v==t){min=MAX;for(i=top-1;i>=0;i--){if(min>edge[zhan[i]].cap){min=edge[zhan[i]].cap;index=i;}}ans+=min;for(i=top-1;i>=0;i--){edge[zhan[i]].cap-=min;edge[zhan[i]^1].cap+=min;}top=index;v=edge[zhan[top]].u;}for(i=cur[v];i!=-1;i=cur[v]=edge[i].next){if(dis[v]+1==dis[edge[i].v] && edge[i].cap>0){v=edge[i].v;zhan[top++]=i;break;}}if(i==-1){if(top==0)break;top--;dis[v]=-2;  //忘了这个调试的有点久v=edge[zhan[top]].u;}}}return ans;}int main(){int i,j;int n,m;int ds,dt;int z;int l,p;while(scanf("%d%d",&n,&m)!=EOF){scanf("%d%d",&ds,&dt);memset(head,-1,sizeof(head));num=0;s=0;t=2*n+1;for(i=1;i<=n;i++){scanf("%d",&z);add(i,i+n,z);}for(i=0;i<m;i++){scanf("%d%d",&l,&p);add(l+n,p,MAX);add(p+n,l,MAX);}add(s,ds,MAX);add(dt+n,t,MAX);printf("%d\n",dinic());}return 0;}