hdu 2485(最小费用最大流)

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

思路:题目的意思是删除最少的点使1,n的最短路大于k。将点转化为边,容量为1,费用为0,然后就是对于那些有道路的城市之间连边,若(u,v)有边,则连边(u+n)->v,容量为inf,费用为花费的时间1,然后就是跑最小费了,若dist[vt]>k,则返回false,最后输出的flow就代表要删除的点的个数。

 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 MAXM 4444444
 9 #define inf 1<<30
10 
11 struct Edge{
12     int v,cap,cost,next;
13 }edge[MAXM];
14 
15 int n,m,k,vs,vt,NE;
16 int head[MAXN];
17 
18 void Insert(int u,int v,int cap,int cost)
19 {
20     edge[NE].v=v;
21     edge[NE].cap=cap;
22     edge[NE].cost=cost;
23     edge[NE].next=head[u];
24     head[u]=NE++;
25 
26     edge[NE].v=u;
27     edge[NE].cap=0;
28     edge[NE].cost=-cost;
29     edge[NE].next=head[v];
30     head[v]=NE++;
31 }
32 
33 int dist[MAXN],pre[MAXN],cur[MAXN];
34 bool mark[MAXN];
35 bool spfa(int vs,int vt)
36 {
37     memset(mark,false,sizeof(mark));
38     fill(dist,dist+2*n+1,inf);
39     dist[vs]=0;
40     queue<int>que;
41     que.push(vs);
42     while(!que.empty()){
43         int u=que.front();
44         que.pop();
45         mark[u]=false;
46         for(int i=head[u];i!=-1;i=edge[i].next){
47             int v=edge[i].v,cost=edge[i].cost;
48             if(edge[i].cap>0&&dist[u]+cost<dist[v]){
49                 dist[v]=dist[u]+cost;
50                 pre[v]=u;
51                 cur[v]=i;
52                 if(!mark[v]){
53                     mark[v]=true;
54                     que.push(v);
55                 }
56             }
57         }
58     }
59     if(dist[vt]>k)return false;
60     return dist[vt]!=inf;
61 }
62 
63 int MinCostFlow(int vs,int vt)
64 {
65     int flow=0,cost=0;
66     while(spfa(vs,vt)){
67         int aug=inf;
68         for(int u=vt;u!=vs;u=pre[u]){
69             aug=min(aug,edge[cur[u]].cap);
70         }
71         flow+=aug,cost+=dist[vt]*aug;
72         for(int u=vt;u!=vs;u=pre[u]){
73             edge[cur[u]].cap-=aug;
74             edge[cur[u]^1].cap+=aug;
75         }
76     }
77     return flow;
78 }
79 
80 int main()
81 {
82     int u,v;
83     while(~scanf("%d%d%d",&n,&m,&k)){
84         if(n==0&&m==0&&k==0)break;
85         NE=0;
86         vs=1,vt=n;
87         memset(head,-1,sizeof(head));
88         for(int i=2;i<=n-1;i++)Insert(i,i+n,1,0);
89         while(m--){
90             scanf("%d%d",&u,&v);
91             if(u==vs)Insert(vs,v,inf,1);
92             else Insert(u+n,v,inf,1);
93         }
94         printf("%d\n",MinCostFlow(vs,vt));
95     }
96     return 0;
97 }
View Code

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值