[SDOI2009]晨跑

这道题是一个很裸的费用流题目。

一般点之过一次的套路就是拆点连边。

其他的模拟下就水过去了。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define re register
 6 #define rep(i, a, b) for (re int i = a; i <= b; ++i)
 7 #define repd(i, a, b) for (re int i = a; i >= b; --i)
 8 #define maxx(a, b) a = max(a, b);
 9 #define minn(a, b) a = min(a, b);
10 #define LL long long
11 #define INF (1 << 30)
12 
13 inline int read() {
14     int w = 0, f = 1; char c = getchar();
15     while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar();
16     while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar();
17     return w * f;
18 }
19 
20 const int maxn = 200 + 10, maxm = 20000 + 10;
21 
22 struct Edge {
23     int u, v, c, f, w, pre;
24 };
25 
26 int mincost = INF;
27 
28 struct Graph {
29     Edge ed[maxm << 2];
30     int n, m, G[maxn << 1];
31     void init(int n) {
32         this->n = n;
33         m = 1;
34         memset(G, 0, sizeof(G));
35     }
36     void add(int u, int v, int c, int w) {
37         ed[++m] = (Edge){u, v, c, 0, w, G[u]};
38         G[u] = m;
39         ed[++m] = (Edge){v, u, 0, 0, -w, G[v]};
40         G[v] = m;
41     }
42     int a[maxn << 1], d[maxn << 1], p[maxn << 1], inq[maxn << 1];
43     int s, t;
44     queue<int> Q;
45     bool spfa(int &flow, int &cost) {
46         memset(inq, 0, sizeof(inq));
47         rep(i, 1, n) d[i] = INF;
48         d[s] = 0;
49         a[s] = INF;
50         Q.push(s); inq[s] = 1;
51         while (!Q.empty()) {
52             int u = Q.front(); Q.pop(); inq[u] = 0;
53             for (register int i = G[u]; i; i = ed[i].pre) {
54                 Edge &e = ed[i];
55                 if (e.f < e.c && d[u] + e.w < d[e.v]) {
56                     d[e.v] = d[u] + e.w;
57                     a[e.v] = min(a[u], e.c-e.f);
58                     p[e.v] = i;
59                     if (!inq[e.v]) Q.push(e.v), inq[e.v] = 1;
60                 }
61             }
62         }
63         if (d[t] == INF) return false;
64         flow += a[t];
65         cost += a[t] * d[t];
66         for (register int i = p[t]; i; i = p[ed[i].u]) {
67             ed[i].f += a[t];
68             ed[i^1].f -= a[t];
69         }
70         return true;
71     }
72     int mcmf(int s, int t, int &cost) {
73         this->s = s, this->t = t;
74         int flow = 0; cost = 0;
75         while (spfa(flow, cost));
76         return flow;
77     }
78 } G;
79 
80 int n, m;
81 
82 int main() {
83     n = read(), m = read(); G.init(n*2);
84     rep(i, 1, m) {
85         int u = read(), v = read(), w = read();
86         G.add(u+n, v, 1, w);
87     }
88     rep(i, 2, n-1) G.add(i, i+n, 1, 0);
89     G.add(n, n*2, INF, 0);
90     G.add(1, n+1, INF, 0);
91     int cost;
92     printf("%d", G.mcmf(1, n*2, cost));
93     printf(" %d", cost);
94     return 0;
95 }

 

转载于:https://www.cnblogs.com/ac-evil/p/10367440.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值