题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3904
思路:费用流的题,增加一个超级源点和一个超级汇点,然后就是连边了,对于每个城市,与汇点连边,容量为inf,花费(这里指收益)为商品在该城市的价值,然后对于图中给定的边,容量为cap,花费为-cost(负数代表花费),最后就是源点与城市1连边了,然后就是跑费用流了,求最大收益(当dist[vt]<0时直接退出)。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 #define MAXN 222 8 #define inf 1<<30 9 10 struct Edge{ 11 int v,cap,cost,next; 12 }edge[MAXN*MAXN]; 13 14 int n,m,vs,vt,NE; 15 int head[MAXN]; 16 17 void Insert(int u,int v,int cap,int cost) 18 { 19 edge[NE].v=v; 20 edge[NE].cap=cap; 21 edge[NE].cost=cost; 22 edge[NE].next=head[u]; 23 head[u]=NE++; 24 25 edge[NE].v=u; 26 edge[NE].cap=0; 27 edge[NE].cost=-cost; 28 edge[NE].next=head[v]; 29 head[v]=NE++; 30 } 31 32 bool mark[MAXN]; 33 int dist[MAXN],pre[MAXN],cur[MAXN]; 34 bool spfa(int vs,int vt) 35 { 36 memset(mark,false,sizeof(mark)); 37 fill(dist,dist+MAXN,-inf); 38 dist[vs]=0; 39 queue<int>que; 40 que.push(vs); 41 while(!que.empty()){ 42 int u=que.front(); 43 que.pop(); 44 mark[u]=false; 45 for(int i=head[u];i!=-1;i=edge[i].next){ 46 int v=edge[i].v,cost=edge[i].cost; 47 if(edge[i].cap>0&&dist[u]+cost>dist[v]){ 48 dist[v]=dist[u]+cost; 49 pre[v]=u; 50 cur[v]=i; 51 if(!mark[v]){ 52 mark[v]=true; 53 que.push(v); 54 } 55 } 56 } 57 } 58 return dist[vt]>0; 59 } 60 61 int MinCostFlow(int vs,int vt) 62 { 63 int flow=0,cost=0; 64 while(spfa(vs,vt)){ 65 int aug=inf; 66 for(int u=vt;u!=vs;u=pre[u]){ 67 aug=min(aug,edge[cur[u]].cap); 68 } 69 flow+=aug,cost+=aug*dist[vt]; 70 for(int u=vt;u!=vs;u=pre[u]){ 71 edge[cur[u]].cap-=aug; 72 edge[cur[u]^1].cap+=aug; 73 } 74 } 75 return cost; 76 } 77 78 int main() 79 { 80 int x,u,v,cap,cost; 81 while(~scanf("%d%d",&n,&m)){ 82 vs=0,vt=n+1; 83 NE=0; 84 memset(head,-1,sizeof(head)); 85 for(int i=2;i<=n;i++){ 86 scanf("%d",&x); 87 Insert(i,vt,inf,x); 88 } 89 while(m--){ 90 scanf("%d%d%d%d",&u,&v,&cap,&cost); 91 Insert(u,v,cap,-cost); 92 Insert(v,u,cap,-cost); 93 } 94 Insert(vs,1,inf,0); 95 printf("%d\n",MinCostFlow(vs,vt)); 96 } 97 return 0; 98 }