hlg1392Leyni, LOLI and Houses【网络流+二分+floyed】
今天过了几道网络流的题, 下面下一下解题报告, 题目难易不是梯度的 ,还有一些题目的代码在 voj上 等有空会补上的
Leyni, LOLI and Houses | ||||||
|
||||||
Description | ||||||
Leyni likes to play with LOLIs. Leyni is playing with LOLIs outdoors, but suddenly it begins to rain, so the LOLI s need to enter some house in order to shelter from the rain.
There are m houses and n LOLIs. The houses locations are numbered by 1..m; the LOLIs are numbered by m+1..m+n. Each house can accommodate up to c LOLIs. There are some paths among the LOLIs and the houses. You can think the distance and the time required to walk is equal.(e.g. Distance between LOLIx and LOLIy are d, then the time required for walking from LOLIx to LOLIy is d.) LOLIs can also traverse several paths on the way to their houses.(e.g. There are paths LOLIx=> LOLIy and LOLIy => housez, then LOLIx can reach housez by the paths LOLIx => LOLIy => housez)
In order to express his love and care for LOLIs, Leyni needs to wait until all LOLIs have entered the houses. Then he will go home. (The LOLIs begin to walk at the same time and concurrently) Leyni wants to find an assignment for each LOLI to some house so that the time for him to wait is minimized (and, of course, the houses are not over utilized). Please help him calculate the minimum time to wait. |
||||||
Input | ||||||
There are multiple test cases. The first line of input is an integer T indicating the number of test cases. Then T test cases follow. For each test case: Line 1. This line contains three space-separated integers, m(1 ≤ m ≤ 30), n(1 ≤ n ≤ 200), and c(1 ≤ c ≤ 15). Lines 2..1+m+n. There is an (m + n) * (m + n) matrix MAT (0 ≤ MATij ≤ 200), the element MATij means the distance between entity i and entity j. It means that entity i and entity j is not directly connected if MATij = 0. (It is guaranteed that the element on the diagonal line will always be 0 and MATij = MATji) |
||||||
Output | ||||||
For each test case: Line 1. Output the minimum possible total distance for the furthest walking LOLI. |
||||||
Sample Input | ||||||
1 2 3 2 0 3 2 1 1 3 0 3 2 0 2 3 0 1 0 1 2 1 0 2 1 0 0 2 0 |
||||||
Sample Output | ||||||
2 |
||||||
Source | ||||||
哈理工2012春季校赛 - 现场赛 | ||||||
Author | ||||||
齐达拉图@HRBUST |
大意:
有m个房子和n个萝莉(房子编号1--m,萝莉编号m + 1 -- m + n)
现在萝莉要走到房间里去,但是, 你每个房间最多能容纳c个萝莉,并且萝莉跟每个房间都有一定的距离,我们还知道萝莉能够穿过一个房间到另一个房间
求所走距离最大的那个萝莉的距离最小值(前提是所有萝莉都能到房间并且房间不会超过上限)
模型:
1、任意两点都要求距离:floyed算法 n*n*n
2、最大距离的最小值:二分
3、所有萝莉都能到大房间,房间还有上限:网络流
思路:
用floyed处理处两点之间的最短距离,然后二分最大距离的最小值,建图求最大流是否等于萝莉数
wrong的原因:房屋和萝莉的编号搞错了
全都是泪啊
代码:
1 //1392 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <vector> 6 #include <queue> 7 using namespace std; 8 9 const int maxn = 30 * 200 + 10; 10 const int INF = 1000000000; 11 12 const int maxm = 30 + 200 + 10; 13 int a[maxn][maxn]; 14 int m, n, c; 15 int ss, tt; 16 17 struct Edge 18 { 19 int from, to, cap, flow; 20 }; 21 22 struct Dinic 23 { 24 int n, m, s, t; 25 vector<Edge> edges; 26 vector<int>G[maxn]; 27 bool vis[maxn]; 28 int d[maxn]; 29 int cur[maxn]; 30 31 void ClearAll(int n) { 32 for(int i = 0; i <= n; i++) { 33 G[i].clear(); 34 } 35 edges.clear(); 36 } 37 38 void AddEdge(int from, int to, int cap) { 39 edges.push_back((Edge){from, to, cap, 0} ); 40 edges.push_back((Edge){to, from, 0, 0} ); 41 m = edges.size(); 42 G[from].push_back(m - 2); 43 G[to].push_back(m - 1); 44 //printf("%din end\n",m); 45 } 46 47 bool BFS() 48 { 49 memset(vis, 0, sizeof(vis) ); 50 queue<int> Q; 51 Q.push(s); 52 vis[s] = 1; 53 d[s] = 0; 54 while(!Q.empty() ){ 55 int x = Q.front(); Q.pop(); 56 for(int i = 0; i < G[x].size(); i++) { 57 Edge& e = edges[G[x][i]]; 58 if(!vis[e.to] && e.cap > e.flow) { 59 vis[e.to] = 1; 60 d[e.to] = d[x] + 1; 61 Q.push(e.to); 62 } 63 } 64 } 65 return vis[t]; 66 } 67 68 int DFS(int x, int a) { 69 if(x == t || a == 0) return a; 70 int flow = 0, f; 71 for(int& i = cur[x]; i < G[x].size(); i++) { 72 Edge& e = edges[G[x][i]]; 73 if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0) { 74 e.flow += f; 75 edges[G[x][i]^1].flow -= f; 76 flow += f; 77 a -= f; 78 if(a == 0) break; 79 } 80 } 81 return flow; 82 } 83 84 int MaxFlow(int s, int t) { 85 this -> s = s; this -> t = t; 86 int flow = 0; 87 while(BFS()) { 88 memset(cur, 0, sizeof(cur)); 89 flow += DFS(s, INF); 90 } 91 return flow; 92 } 93 }; 94 95 Dinic g; 96 97 bool Check(int num) { 98 if(n > m * c) 99 return false; 100 //printf("*%d\n",num); 101 g.ClearAll(maxn); 102 103 for(int i = m + 1; i <= m + n; i++) { 104 g.AddEdge(ss, i, 1); 105 } 106 107 for(int i = 1; i <= m; i++) { 108 g.AddEdge(i, tt, c); 109 } 110 111 for(int i = m + 1; i <= m + n; i++) { 112 for(int j = 1; j <= m; j++) { 113 if(a[i][j] <= num) { 114 //printf("(%d,%d)\n",i, j); 115 g.AddEdge(i, j, INF); 116 } 117 } 118 } 119 int ans = g.MaxFlow(ss, tt); 120 //printf("%d %d\n",ans, n); 121 if(ans == n) 122 return true; 123 else 124 return false; 125 } 126 127 128 void Floyed() { 129 int nNode = n + m; 130 for(int k = 1; k <= nNode; k++) { 131 for(int i = 1; i <= nNode; i++) { 132 for(int j = 1; j <= nNode; j++) { 133 if(k == i || k == j ) continue; 134 if(a[i][j] > a[i][k] + a[k][j]) { 135 a[i][j] = a[i][k] + a[k][j]; 136 } 137 } 138 } 139 } 140 } 141 142 int main() { 143 int t; 144 //freopen("b.txt","r",stdin); 145 scanf("%d",&t); 146 while(t--) { 147 scanf("%d %d %d",&m, &n, &c); 148 ss = 0; tt = n + m + 1; 149 for(int i = 1; i <= m + n; i++) { 150 for(int j = 1; j <= m + n; j++) { 151 scanf("%d",&a[i][j]); 152 if(a[i][j] == 0) { 153 a[i][j] = INF; 154 } 155 } 156 } 157 Floyed(); 158 //Check(0); 159 /* 160 for(int i = 1; i <= m + n; i++) { 161 for(int j = 1; j <= m + n; j++) { 162 printf("%d ",a[i][j]); 163 } 164 puts(""); 165 }*/ 166 //puts("END"); 167 int low = 0, high = maxn; 168 while(low <= high) { 169 int mid = (low + high) >> 1; 170 //printf("%d %d\n",mid, Check(mid)); 171 if(!Check(mid)) { 172 low = mid + 1; 173 } else { 174 high = mid - 1; 175 } 176 } 177 //puts(""); 178 //printf("%d %d\n",low, high); 179 printf("%d\n",high + 1); 180 } 181 return 0; 182 }