zoj 3362(最大费用)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3904

思路:费用流的题,增加一个超级源点和一个超级汇点,然后就是连边了,对于每个城市,与汇点连边,容量为inf,花费(这里指收益)为商品在该城市的价值,然后对于图中给定的边,容量为cap,花费为-cost(负数代表花费),最后就是源点与城市1连边了,然后就是跑费用流了,求最大收益(当dist[vt]<0时直接退出)。

 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 }
View Code

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值