hlg1392Leyni, LOLI and Houses【网络流+二分+floyed】

今天过了几道网络流的题, 下面下一下解题报告, 题目难易不是梯度的 ,还有一些题目的代码在 voj上 等有空会补上的

 

Leyni, LOLI and Houses
Time Limit: 2000 MS Memory Limit: 65536 K
Total Submit: 43(12 users) Total Accepted: 19(11 users) Rating:  Special Judge: No
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 }
View Code

 

posted @ 2014-05-23 20:38  悠悠我心。  阅读(305)  评论(0编辑  收藏  举报