标签:最大流 acm 二分
Problem Description
While DUT is hosting this NECPC Contest, in order to control the expenditure, careful considerations should be given in many respects, such as the layout of the contest venue. When the contest venue is arranged, each computer requires power input. While the layout of computers and power-points are already fixed, some lines have to be purchased to link the computers with power-points. And, Raven finds out that it is cheaper to buy power lines of the same length than to buy lines of different lengths, so he would buy all the lines with the same length. If Raven wants to save money, would you help him?
Input Details
The first line of the input contains an integer T, which indicates the number of test cases.
For each test case, there are three positive integers in the first row, n, m, p (0 <= n, m <= 200,0 < p < 100). It means that there are n computers and m power-points. The power line costs ¥p per unit.
In the following n rows, i-th line has m positive integers indicating the distances between the i-th computer and all the power points. The distance is less than 10000.
In the last row, there are m positive integers, ci (0 < ci < 5,0 <= i < m), showing No.i power-point can provide power to ci computers in total.
Output Details
For each case, if the layout of computers and power lines are not reasonable, which means you cannot provide power to every computer, just output -1.
Otherwise, output the lowest total price for power lines.
Sample Input
1
2 2 1
1 3
2 2
1 1
Sample Output
4
Hint:
You many link the first computer with the first power-points, and link the second computer with the second power-points. This will cost 4(2*2).
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> using namespace std; const int MAXN = 810; const int MAXM = 90000; const int INF = 0x3f3f3f3f; struct Edge { int from, to, cap, next, oricap; }; Edge edge[MAXM]; int head[MAXN]; int cap[MAXN]; int dist[MAXN][MAXN]; int level[MAXN]; int src, des, cnt; void addedge( int from, int to, int cap ) { edge[cnt].from = from; edge[cnt].to = to; edge[cnt].cap = cap; edge[cnt].oricap = cap; edge[cnt].next = head[from]; head[from] = cnt++; swap( from, to ); edge[cnt].from = from; edge[cnt].to = to; edge[cnt].cap = 0; edge[cnt].oricap = 0; edge[cnt].next = head[from]; head[from] = cnt++; } int bfs( ) { memset( level, -1, sizeof level ); queue<int> q; while (!q.empty( )) q.pop( ); level[src] = 0; q.push( src ); while (!q.empty( )) { int u = q.front( ); q.pop( ); for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (edge[i].cap > 0 && level[v] == -1) { level[v] = level[u] + 1; q.push( v ); } } } return level[des] != -1; } int dfs( int u, int f ) { if (u == des) return f; int tem; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (edge[i].cap > 0 && level[v] == level[u] + 1) { tem = dfs( v, min( f, edge[i].cap ) ); if (tem > 0) { edge[i].cap -= tem; edge[i ^ 1].cap += tem; return tem; } } } level[u] = -1; return 0; } int Dinic( ) { int ans = 0, tem; while (bfs( )) { while ((tem = dfs( src, INF )) > 0) { ans += tem; } } return ans; } int main( ) { int kase; cin >> kase; while (kase--) { int n, m, p; cin >> n >> m >> p; src = 0; des = 805; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> dist[i][j]; } } for (int i = 1; i <= m; i++) cin >> cap[i]; int low = 0, high = INF - 1; int ans = -1; while (low <= high) { int mid = (high + low) / 2; memset( head, -1, sizeof head ); cnt = 0; for (int i = 1; i <= n; i++) { addedge( src, i, 1 ); } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (dist[i][j] <= mid) addedge( i, j + 200, 1 ); } } for (int i = 1; i <= m; i++) { addedge( i + 200, des, cap[i] ); } if (Dinic() < n) low = mid + 1; else { ans = mid; high = mid - 1; } } if (low >= INF - 1) cout << -1 << endl; else cout << ans*p*n << endl; } return 0; }
标签:最大流 acm 二分
原文地址:http://blog.csdn.net/maxichu/article/details/45232711