1. 程式人生 > >洛谷P3980 志願者招募

洛谷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了之後我自以為建圖很奇葩,跑去看題解,發現都是這種解法......

還可以用線性規劃做...好神奇啊。