Uva 10983 Buy one, get the rest free(二分+最大流)

来源:互联网 发布:如何求矩阵的特征向量 编辑:程序博客网 时间:2024/06/03 15:37

题目地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1924

思路:

1.二分所需花费cost,每次只选择不大于cost的航班。

2.设源点S,汇点T。对于每个城市,表示为二元组(i,t),代表第t天处于第i个城市。从S到每一(i,0)连边,容量为每个城市人数;从(n,d)到T连边,容量为INF。

3.对于每个个航班,从城市i到城市j,出发时间为e,到达时间为e+1。连边(i,e)->(j,e+1),容量为航班限制人数。

4.由于可在城市停留,连边(i,e)->(i,e+1),容量为INF。

5.若最大流等于总人数,则当前花费可满足条件。

#include<queue>#include<cmath>#include<cstdio>#include<vector>#include<cstring>#include<iostream>#include<algorithm>#define debugusing namespace std;const int maxn = 400 + 50;const int maxm = 1000 + 50;const int INF = 0x3f3f3f3f;struct Edge{int from, to, cap, flow;Edge(int a, int b, int c, int d) :from(a), to(b), cap(c), flow(d) {}};struct Dinic{int n, m, s, t;vector<Edge> edges;vector<int> G[maxn];bool vis[maxn];int d[maxn];int cur[maxn];void init(int n){this->n = n;for (int i = 0; i <= n; i++) G[i].clear();edges.clear();}void addEdge(int from, int to, int cap){edges.push_back(Edge(from, to, cap, 0));edges.push_back(Edge(to, from, 0, 0));m = edges.size();G[from].push_back(m - 2);G[to].push_back(m - 1);}bool BFS(){memset(vis, 0, sizeof(vis));queue<int> Q;Q.push(s);vis[s] = 1;d[s] = 0;while (!Q.empty()){int x = Q.front();Q.pop();for (int i = 0; i < G[x].size(); i++){Edge& e = edges[G[x][i]];if (!vis[e.to] && e.cap > e.flow){vis[e.to] = 1;d[e.to] = d[x] + 1;Q.push(e.to);}}}return vis[t];}int DFS(int x, int a){if (x == t || a == 0) return a;int flow = 0, f;for (int& i = cur[x]; i < G[x].size(); i++){Edge& e = edges[G[x][i]];if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0){e.flow += f;edges[G[x][i] ^ 1].flow -= f;flow += f;a -= f;if (a == 0) break;}}return flow;}int MaxFlow(int s, int t){this->s = s;this->t = t;int flow = 0;while (BFS()){memset(cur, 0, sizeof(cur));flow += DFS(s, INF);}return flow;}};struct Node{int u, v, c, p, e;};Dinic g;int p[40];Node a[maxm];int id[40][15];int n, d, m, maxx;int cnt, S, T, sum;int check(int x){g.init(cnt + 1);for (int i = 1; i <= n; i++){g.addEdge(S, id[i][0], p[i]);for (int j = 0; j <= d; j++){g.addEdge(id[i][j], id[i][j + 1], INF);}}g.addEdge(id[n][d], T, INF);for (int i = 0; i < m; i++){Node& tmp = a[i];if (tmp.p <= x){g.addEdge(id[tmp.u][tmp.e], id[tmp.v][tmp.e + 1], tmp.c);}}return g.MaxFlow(S, T) == sum;}void init(){cnt = 0;sum = 0;maxx = -INF;memset(id, 0, sizeof(id));}int main(){#ifdef debufreopen("in.txt", "r", stdin);#endifint t, cas = 0;scanf("%d", &t);while (t--){scanf("%d%d%d", &n, &d, &m);init();for (int i = 1; i <= n; i++){for (int j = 0; j <= d; j++){id[i][j] = ++cnt;}}for (int i = 0; i < m; i++){int u, v, c, p, e;scanf("%d%d%d%d%d", &u, &v, &c, &p, &e);a[i] = Node{ u,v,c,p,e };maxx = max(maxx, p);}S = 0, T = cnt + 1;g.init(cnt + 1);for (int i = 1; i <= n; i++){scanf("%d", &p[i]);sum += p[i];}int l = 0, r = maxx, ans = -1;while (l <= r){int mid = (l + r) >> 1;if (check(mid)){r = mid - 1;ans = mid;}else{l = mid + 1;}}printf("Case #%d: ", ++cas);if (ans == -1) printf("Impossible\n");else printf("%d\n", ans);}return 0;}



阅读全文
0 0
原创粉丝点击