洛谷P3980 志愿者招募

题意:懒得写了......

解:

一开始想的是每天建点,每种人建点,然后连边费用流,发现一个人可以管辖多天,不好处理。

回想起了网络流24题中的"最长k可重线段集","最长k可重区间集"等问题,然后发现这题也可以横着流啊。

具体来说,首先在下面开一条安全快速绿色通道,存放那些不用的人(流量)。

那么每天要用怎么办?把人逼出去!

流量设为INF - ai就可以逼出去ai个人了!

然后每种人都对应一段区间,连边跑最小费用最大流即可。

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <queue>
 4 #include <cstring>
 5 
 6 const int N = 1010, M = 1000010, INF = 0x3f3f3f3f;
 7 
 8 struct Edge {
 9     int nex, v, c, len;
10 }edge[M << 1]; int top = 1;
11 
12 int e[N], d[N], vis[N], pre[N], flow[N];
13 std::queue<int> Q;
14 
15 inline void add(int x, int y, int z, int w) {
16     top++;
17     edge[top].v = y;
18     edge[top].c = z;
19     edge[top].len = w;
20     edge[top].nex = e[x];
21     e[x] = top;
22 
23     top++;
24     edge[top].v = x;
25     edge[top].c = 0;
26     edge[top].len = -w;
27     edge[top].nex = e[y];
28     e[y] = top;
29     return;
30 }
31 
32 inline bool SPFA(int s, int t) {
33     memset(d, 0x3f, sizeof(d));
34     d[s] = 0;
35     flow[s] = INF;
36     vis[s] = 1;
37     Q.push(s);
38     while(!Q.empty()) {
39         int x = Q.front();
40         Q.pop();
41         vis[x] = 0;
42         for(int i = e[x]; i; i = edge[i].nex) {
43             int y = edge[i].v;
44             if(edge[i].c && d[y] > d[x] + edge[i].len) {
45                 d[y] = d[x] + edge[i].len;
46                 pre[y] = i;
47                 flow[y] = std::min(flow[x], edge[i].c);
48                 if(!vis[y]) {
49                     vis[y] = 1;
50                     Q.push(y);
51                 }
52             }
53         }
54     }
55     return d[t] < INF;
56 }
57 
58 inline void update(int s, int t) {
59     int temp = flow[t];
60     while(t != s) {
61         int i = pre[t];
62         edge[i].c -= temp;
63         edge[i ^ 1].c += temp;
64         t = edge[i ^ 1].v;
65     }
66     return;
67 }
68 
69 inline int solve(int s, int t, int &cost) {
70     int ans = 0;
71     cost = 0;
72     while(SPFA(s, t)) {
73         ans += flow[t];
74         cost += flow[t] * d[t];
75         update(s, t);
76     }
77     return ans;
78 }
79 
80 int main() {
81     int n, m;
82     scanf("%d%d", &n, &m);
83     for(int i = 1, x; i <= n; i++) {
84         scanf("%d", &x);
85         add(i, i + 1, INF - x, 0);
86     }
87     for(int i = 1, x, y, z; i <= m; i++) {
88         scanf("%d%d%d", &x, &y, &z);
89         add(x, y + 1, INF, z);
90     }
91     int s = n + 2;
92     add(s, 1, INF, 0);
93     int ans;
94     solve(s, n + 1, ans);
95     printf("%d", ans);
96     return 0;
97 }
AC代码

题外话:A了之后我自以为建图很奇葩,跑去看题解,发现都是这种解法......

还可以用线性规划做...好神奇啊。

posted @ 2018-12-13 22:10  huyufeifei  阅读(249)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

ReadEra 阅读书籍

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜