hdu 4289(最小割)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4289

思路:求最小花费,最小割应用,将点权转化为边权,拆点,(i,i+n)之间连边,容量为在城市i的花费,然后就是若u,v之间有路,则连边(u+n,v),(v+n,u).最后就是跑最大流了。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 using namespace std;
  7 #define MAXN 444
  8 #define MAXM 44444444
  9 #define inf 1<<30
 10 
 11 struct Edge{
 12     int v,cap,next;
 13 }edge[MAXM];
 14 
 15 int n,m,vs,vt,NE,NV;
 16 int head[MAXN];
 17 
 18 void Insert(int u,int v,int cap)
 19 {
 20     edge[NE].v=v;
 21     edge[NE].cap=cap;
 22     edge[NE].next=head[u];
 23     head[u]=NE++;
 24 
 25     edge[NE].v=u;
 26     edge[NE].cap=0;
 27     edge[NE].next=head[v];
 28     head[v]=NE++;
 29 }
 30 
 31 int level[MAXN],gap[MAXN];
 32 void bfs(int vt)
 33 {
 34     memset(level,-1,sizeof(level));
 35     memset(gap,0,sizeof(gap));
 36     level[vt]=0;
 37     gap[level[vt]]++;
 38     queue<int>que;
 39     que.push(vt);
 40     while(!que.empty()){
 41         int u=que.front();
 42         que.pop();
 43         for(int i=head[u];i!=-1;i=edge[i].next){
 44             int v=edge[i].v;
 45             if(level[v]!=-1)continue;
 46             level[v]=level[u]+1;
 47             gap[level[v]]++;
 48             que.push(v);
 49         }
 50     }
 51 }
 52 
 53 int pre[MAXN],cur[MAXN];
 54 int SAP(int vs,int vt)
 55 {
 56     bfs(vt);
 57     memset(pre,-1,sizeof(pre));
 58     memcpy(cur,head,sizeof(head));
 59     int maxflow=0,aug=inf;
 60     int u=pre[vs]=vs;
 61     gap[0]=NV;
 62     while(level[vs]<NV){
 63         bool flag=false;
 64         for(int &i=cur[u];i!=-1;i=edge[i].next){
 65             int v=edge[i].v;
 66             if(edge[i].cap>0&&level[u]==level[v]+1){
 67                 flag=true;
 68                 pre[v]=u;
 69                 u=v;
 70                 aug=min(aug,edge[i].cap);
 71                 if(v==vt){
 72                     maxflow+=aug;
 73                     for(u=pre[v];v!=vs;v=u,u=pre[u]){
 74                         edge[cur[u]].cap-=aug;
 75                         edge[cur[u]^1].cap+=aug;
 76                     }
 77                     aug=inf;
 78                 }
 79                 break;
 80             }
 81         }
 82         if(flag)continue;
 83         int minlevel=NV;
 84         for(int i=head[u];i!=-1;i=edge[i].next){
 85             int v=edge[i].v;
 86             if(edge[i].cap>0&&level[v]<minlevel){
 87                 cur[u]=i;
 88                 minlevel=level[v];
 89             }
 90         }
 91         if(--gap[level[u]]==0)break;
 92         level[u]=minlevel+1;
 93         gap[level[u]]++;
 94         u=pre[u];
 95     }
 96     return maxflow;
 97 }
 98 
 99 int main()
100 {
101     int u,v,w;
102     while(~scanf("%d%d",&n,&m)){
103         NE=0,NV=2*n;
104         memset(head,-1,sizeof(head));
105         scanf("%d%d",&vs,&vt);
106         for(int i=1;i<=n;i++){
107             scanf("%d",&w);
108             Insert(i,i+n,w);
109         }
110         while(m--){
111             scanf("%d%d",&u,&v);
112             Insert(u+n,v,inf);
113             Insert(v+n,u,inf);
114         }
115         printf("%d
",SAP(vs,vt+n));
116     }
117     return 0;
118 }
View Code
原文地址:https://www.cnblogs.com/wally/p/3286692.html