大致题意:
给出一个又n个点,m条边组成的无向图。给出两个点s,t。对于图中的每个点,去掉这个点都需要一定的花费。求至少多少花费才能使得s和t之间不连通。
大致思路:
最基础的拆点最大流,把每个点拆作两个点 i 和 i' 连接i->i'费用为去掉这个点的花费,如果原图中有一条边a->b则连接a'->b。对这个图求出最大流即可。
画了个图,仔细看看似乎是这么回事
1 //1002 2 /* 3 HDU 4289 4 G++ 62ms 1888K 5 最大流 6 SAP 7 */ 8 #include<stdio.h> 9 #include<iostream> 10 #include<map> 11 #include<set> 12 #include<algorithm> 13 #include<string.h> 14 #include<stdlib.h> 15 using namespace std; 16 17 const int MAXN=5000;//点数的最大值 18 const int MAXM=2500000;//边数的最大值 19 const int INF=0x3f3f3f3f; 20 21 struct Node 22 { 23 int from,to,next; 24 int cap; 25 }edge[MAXM]; 26 int tol; 27 int head[MAXN]; 28 int dep[MAXN]; 29 int gap[MAXN];//gap[x]=y:说明残留网络中 dep[i]==x的个数为y 30 31 int n;//点的实际个数,一定是总的点的个数,包括源点和汇点 32 void init() 33 { 34 tol=0; 35 memset(head,-1,sizeof(head)); 36 } 37 void addedge(int u,int v,int w) 38 { 39 edge[tol].from=u; 40 edge[tol].to=v; 41 edge[tol].cap=w; 42 edge[tol].next=head[u]; 43 head[u]=tol++; 44 edge[tol].from=v; 45 edge[tol].to=u; 46 edge[tol].cap=0; 47 edge[tol].next=head[v]; 48 head[v]=tol++; 49 } 50 void BFS(int start,int end) 51 { 52 memset(dep,-1,sizeof(dep)); 53 memset(gap,0,sizeof(gap)); 54 gap[0]=1; 55 int que[MAXN]; 56 int front,rear; 57 front=rear=0; 58 dep[end]=0; 59 que[rear++]=end; 60 while(front!=rear) 61 { 62 int u=que[front++]; 63 if(front==MAXN)front=0; 64 for(int i=head[u];i!=-1;i=edge[i].next) 65 { 66 int v=edge[i].to; 67 if(edge[i].cap!=0||dep[v]!=-1)continue; 68 que[rear++]=v; 69 if(rear==MAXN)rear=0; 70 dep[v]=dep[u]+1; 71 ++gap[dep[v]]; 72 } 73 } 74 } 75 int SAP(int start,int end) 76 { 77 int res=0; 78 BFS(start,end); 79 int cur[MAXN]; 80 int S[MAXN]; 81 int top=0; 82 memcpy(cur,head,sizeof(head)); 83 int u=start; 84 int i; 85 while(dep[start]<n) 86 { 87 if(u==end) 88 { 89 int temp=INF; 90 int inser; 91 for(i=0;i<top;i++) 92 if(temp>edge[S[i]].cap) 93 { 94 temp=edge[S[i]].cap; 95 inser=i; 96 } 97 for(i=0;i<top;i++) 98 { 99 edge[S[i]].cap-=temp; 100 edge[S[i]^1].cap+=temp; 101 } 102 res+=temp; 103 top=inser; 104 u=edge[S[top]].from; 105 } 106 if(u!=end&&gap[dep[u]-1]==0)//出现断层,无增广路 107 break; 108 for(i=cur[u];i!=-1;i=edge[i].next) 109 if(edge[i].cap!=0&&dep[u]==dep[edge[i].to]+1) 110 break; 111 if(i!=-1) 112 { 113 cur[u]=i; 114 S[top++]=i; 115 u=edge[i].to; 116 } 117 else 118 { 119 int min=n; 120 for(i=head[u];i!=-1;i=edge[i].next) 121 { 122 if(edge[i].cap==0)continue; 123 if(min>dep[edge[i].to]) 124 { 125 min=dep[edge[i].to]; 126 cur[u]=i; 127 } 128 } 129 --gap[dep[u]]; 130 dep[u]=min+1; 131 ++gap[dep[u]]; 132 if(u!=start) 133 u=edge[S[--top]].from; 134 } 135 136 } 137 return res; 138 } 139 140 int main() 141 { 142 //freopen("B.in","r",stdin); 143 //freopen("B.out","w",stdout); 144 int N,M; 145 int u,v; 146 int start; 147 int end; 148 while(scanf("%d%d",&N,&M)!=EOF) 149 { 150 init(); 151 scanf("%d%d",&start,&end); 152 start=2*start-1; 153 end=2*end; 154 n=2*N; 155 for(int i=1;i<=N;i++) 156 { 157 scanf("%d",&u); 158 addedge(2*i-1,2*i,u); 159 addedge(2*i,2*i-1,u); 160 } 161 while(M--) 162 { 163 scanf("%d%d",&u,&v); 164 addedge(2*u,2*v-1,INF); 165 addedge(2*v,2*u-1,INF);//这里一定要注意 166 } 167 printf("%d ",SAP(start,end)); 168 } 169 return 0; 170 }