图上的每个点有权值,求使从起点无法到达终点去掉的权值和最小。
因为权值在点上,所以要进行拆点。将i点拆为2i和2i+1。然后流量统一从偶数点进,奇数点出,点之间连流量为点权的有向边,无向边拆成两条有向边,分别向两个端点连两条流量为无穷大的有向边,如下图所示。
1 #include <string.h> 2 #include <stdio.h> 3 #include <algorithm> 4 #define MAXN 500 5 #define MAXE 100000 6 #define INF 0x3f3f3f3f 7 struct edge{ 8 int v,e,n,flow; 9 }e[MAXE]; 10 int first[MAXN],es; 11 int work[MAXN],q[MAXN],d[MAXN],front,rear; 12 void addedge(int u,int v,int flow){ 13 e[es].v=v,e[es].flow=flow,e[es].n=first[u],first[u]=es++; 14 } 15 int bfs(int s,int t,int n){ 16 memset(d,-1,sizeof(d[0])*(n+1)); 17 q[front=rear=d[s]=0]=s,rear++; 18 while(front<rear){ 19 int u=q[front++]; 20 for(int i=first[u];i!=-1;i=e[i].n) 21 if(e[i].flow&&d[e[i].v]==-1){ 22 d[e[i].v]=d[u]+1,q[rear++]=e[i].v; 23 if(e[i].v==t)return 1; 24 } 25 } 26 return 0; 27 } 28 int dfs(int cur,int t,int res){ 29 if(cur==t)return res; 30 for(int &i=work[cur];i!=-1;i=e[i].n) 31 if(e[i].flow&&d[e[i].v]==d[cur]+1) 32 if(int tmp=dfs(e[i].v,t,std::min(res,e[i].flow))){ 33 e[i].flow-=tmp,e[i^1].flow+=tmp; 34 return tmp; 35 } 36 return 0; 37 } 38 int dinic(int s,int t,int n){ 39 int ans=0,tt; 40 while(bfs(s,t,n)){ 41 memcpy(work,first,sizeof(first[0])*(n+1)); 42 while(tt=dfs(s,t,INF))ans+=tt; 43 } 44 return ans; 45 } 46 int n,m,s,t,ci,tu,tv,va; 47 int main(){ 48 //freopen("test.in","r",stdin); 49 while(scanf("%d%d",&n,&m)!=EOF){ 50 scanf("%d%d",&s,&t); 51 int va=INF; 52 memset(first,-1,sizeof first);es=0; 53 for(int i=1;i<=n;i++){ 54 scanf("%d",&ci); 55 addedge(i<<1,i<<1|1,ci); 56 addedge(i<<1|1,i<<1,0); 57 if(i==s||i==t)va=std::min(va,ci); 58 } 59 s=s<<1,t=t<<1|1; 60 for(int i=0;i<m;i++){ 61 scanf("%d%d",&tu,&tv); 62 addedge(tu<<1,tv<<1|1,0); 63 addedge(tv<<1|1,tu<<1,INF); 64 addedge(tv<<1,tu<<1|1,0); 65 addedge(tu<<1|1,tv<<1,INF); 66 } 67 printf("%d\n",std::min(va,dinic(s,t,2*n+2))); 68 } 69 70 return 0; 71 }