bzoj 1877 [SDOI2009]晨跑(最小费用最大流)

 

Description

Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑、仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑。 现在给出一张学校附近的地图,这张地图中包含N个十字路口和M条街道,Elaxia只能从 一个十字路口跑向另外一个十字路口,街道之间只在十字路口处相交。Elaxia每天从寝室出发 跑到学校,保证寝室编号为1,学校编号为N。 Elaxia的晨跑计划是按周期(包含若干天)进行的,由于他不喜欢走重复的路线,所以 在一个周期内,每天的晨跑路线都不会相交(在十字路口处),寝室和学校不算十字路 口。Elaxia耐力不太好,他希望在一个周期内跑的路程尽量短,但是又希望训练周期包含的天 数尽量长。 除了练空手道,Elaxia其他时间都花在了学习和找MM上面,所有他想请你帮忙为他设计 一套满足他要求的晨跑计划。

Input

第一行:两个数N,M。表示十字路口数和街道数。 接下来M行,每行3个数a,b,c,表示路口a和路口b之间有条长度为c的街道(单向)。

Output

两个数,第一个数为最长周期的天数,第二个数为满足最长天数的条件下最短的路程长 度。

Sample Input

7 10
1 2 1
1 3 1
2 4 1
3 4 1
4 5 1
4 6 1
2 5 5
3 6 6
5 7 1
6 7 1

Sample Output

2 11

HINT

对于30%的数据,N ≤ 20,M ≤ 120。
对于100%的数据,N ≤ 200,M ≤ 20000。

【思路】

       最小费用最大流

       拆个点,两点之间连容量1费用0的边保证每个结点只经过一次。按照给的图连边跑一次最小费用最大流就好了,保证了流量最大的情况下费用最小。

【代码】

 1 #include<cmath>
 2 #include<queue>
 3 #include<vector>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<iostream>
 7 #include<algorithm>
 8 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
 9 using namespace std;
10 
11 const int N = 500+5;
12 const int INF = 1e9;
13 
14 struct Edge {
15     int u,v,cap,flow,cost;
16 };
17 struct MCMF {
18     queue<int> q;
19     int n,m,a[N],d[N],p[N],inq[N];
20     vector<Edge> es; vector<int> g[N];
21     void init(int n) {
22         this->n=n;
23         es.clear(); 
24         for(int i=0;i<n;i++) g[i].clear();
25     }
26     void AddEdge(int u,int v,int cap,int cost) {
27         es.push_back((Edge){u,v,cap,0,cost});
28         es.push_back((Edge){v,u,0,0,-cost});
29         int m=es.size();
30         g[u].push_back(m-2),g[v].push_back(m-1);
31     }
32     bool spfa(int s,int t,int& flow,int& cost) {
33         memset(inq,0,sizeof(inq));
34         for(int i=0;i<n;i++) d[i]=INF;
35         d[s]=0; inq[s]=1; q.push(s); a[s]=INF;
36         while(!q.empty()) {
37             int u=q.front(); q.pop(); inq[u]=0;
38             for(int i=0;i<g[u].size();i++) {
39                 Edge& e=es[g[u][i]];
40                 int v=e.v;
41                 if(e.cap>e.flow && d[v]>d[u]+e.cost) {
42                     d[v]=d[u]+e.cost;
43                     p[v]=g[u][i];
44                     a[v]=min(a[u],e.cap-e.flow);
45                     if(!inq[v]) inq[v]=1,q.push(v);
46                 }
47             }
48         }
49         if(d[t]==INF) return 0;
50         flow+=a[t]; cost+=a[t]*d[t];
51         for(int x=t;x!=s;x=es[p[x]].u)
52             es[p[x]].flow+=a[t],es[p[x]^1].flow-=a[t];
53         return 1;
54     }
55     void mcmf(int s,int t,int& flow,int& cost) {
56         flow=cost=0;
57         while(spfa(s,t,flow,cost)) ;
58     }
59 }mc;
60 
61 int n,m;
62 
63 int main() {
64     scanf("%d%d",&n,&m);
65     mc.init(n*2+2);
66     int u,v,w,S=1,T=n+n,flow,cost;
67     for(int i=0;i<m;i++) {
68         scanf("%d%d%d",&u,&v,&w);
69         mc.AddEdge(u+n,v,1,w);
70     }
71     for(int i=2;i<=n;i++)
72         mc.AddEdge(i,i+n,1,0);
73     mc.AddEdge(S,1+n,INF,0);
74     mc.AddEdge(n,T,INF,0);
75     mc.mcmf(S,T,flow,cost);
76     printf("%d %d",flow,cost);
77     return 0;
78 }
原文地址:https://www.cnblogs.com/lidaxin/p/5225315.html