[SDOI2009]晨跑

题目链接

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 inline ll read(){
 5     int x=0,f=1;char ch=getchar();
 6     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
 7     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 8     return x*f;
 9 }
10 
11 /***********************************************************/
12 
13 #define inf 0xffffff
14 const int N = 510;
15 int n,m,ans1,ans2,S,T,idc=1;//偶数开始存,方便异或处理反向边 
16 int dis[N],head[N],q[N],from[N];
17 bool exi[N];
18 
19 struct Edge{
20     int from, to, next, w, c;
21 }ed[100010];
22 
23 void adde(int u, int v, int w, int c){
24     ed[++idc].to = v;
25     ed[idc].w = w;
26     ed[idc].c = c;
27     ed[idc].next = head[u];
28     ed[idc].from = u;
29     head[u] = idc;
30 }
31 
32 bool spfa(){
33     int h=0, t=1, now;
34     for(int i=S; i<=T; i++) dis[i] = inf;
35     q[0] = S; dis[S] = 0; exi[S] = 1;
36     while(h != t){
37         now = q[h]; h++; if(h == 500) h = 0;
38         for(int k=head[now]; k; k=ed[k].next){
39             int v = ed[k].to; 
40             if(ed[k].w && ed[k].c + dis[now] < dis[v]){//更新距离 
41                 dis[v] = dis[now] + ed[k].c;
42                 from[v] = k;//末端点属于的边 
43                 if( !exi[v] ){
44                     exi[v] = 1;
45                     q[t++] = ed[k].to;
46                     if(t == 500) t = 0;//滚动数组 
47                 }
48             }
49         }
50         exi[now] = 0;
51     }
52     return(dis[T] != inf);
53  }
54 
55 void mcf(){
56     int flow = inf;
57     int i = from[T];
58     while( i ){
59         flow = min(flow, ed[i].w);
60         i = from[ed[i].from];
61     }//沿着路径寻找最大流量 
62     ans1++;//多一条路径 
63     i = from[T];
64     while( i ){
65         ans2 += flow * ed[i].c;
66         ed[i].w -= flow;
67         ed[i^1].w += flow;
68         i = from[ed[i].from];
69     }//沿着路径统计花费,顺便调整限流 
70 }
71 
72 int main(){
73     n = read(); m = read();
74     S = 1; T = n+n;
75     for(int i = 1;i <= m;i++){
76         int u, v, w;
77         u = read(); v = read(); w = read();
78         adde(u+n, v, 1, w);
79         adde(v, u+n, 0, -w);
80     }
81     //为了限制点流量,往往选择拆点,i为入点,i+n为出点 
82     for(int i=2; i<n; i++)
83         adde(i, i+n, 1, 0), adde(i+n, i, 0, 0);//拆出来的两点相连,限流 
84     adde(1, S+n, inf, 0); adde(S+n, 1, 0, 0);
85     adde(n, T, inf, 0); adde(T, n, 0, 0);
86     while(spfa()) mcf();
87     printf("%d %d\n", ans1, ans2);
88     return 0;
89 }

 

posted @ 2018-10-06 22:15  ouyang_wsgwz  阅读(128)  评论(0编辑  收藏  举报