码迷,mamicode.com
首页 > 其他好文 > 详细

UVa12549 Sentry Robots (二分图最大匹配,最小点集覆盖)

时间:2016-09-26 06:27:46      阅读:268      评论:0      收藏:0      [点我收藏+]

标签:

题意:http://vjudge.net/problem/UVA-12549

分析:技术分享技术分享技术分享

 一个重要位置有(x,y)两个坐标,而要守住这个重要位置就相当于连一条x到y的弧。选了一个重要位置(x,y)放置机器人相当于选了所有x相同的弧或者y相同的弧。当所有的x或者y被选完的时候就完成了看守。具体来说二分图两列分别表示用编号代表行和列,从源点s向行连一条容量为1的弧,从列向汇点t连一条容量为1的弧,再对于每个重要位置(x,y),连一条从x指向y容量为1的弧,跑一次s-t的最大流,最大流出现是当源点s连出去的弧或者连向汇点的弧全部满载(表示图中行或者列全部被选完)的时候,即完成了二分图最大匹配==最小点集覆盖。有障碍物的情况下需要拆行拆列。

 

  1 #include <cstdio>
  2 #include <set>
  3 #include <queue>
  4 #include <cstring>
  5 #include <vector>
  6 #include <algorithm>
  7 using namespace std;
  8 
  9 const int maxn = 10000 + 5;
 10 const int INF = 0x3f3f3f3f;
 11 
 12 struct Edge {
 13     int from, to, cap, flow;
 14     Edge(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {}
 15 };
 16 
 17 struct EdmondsKarp {
 18     int n, m;
 19     vector<Edge> edges;
 20     vector<int> G[maxn];
 21     int a[maxn];
 22     int p[maxn];
 23 
 24     void init(int n) {
 25         for (int i = 0; i < n; i++) G[i].clear();
 26         edges.clear();
 27     }
 28 
 29     void AddEdge(int from, int to, int cap) {
 30         edges.push_back(Edge(from, to, cap, 0));
 31         edges.push_back(Edge(to, from, 0, 0));
 32         m = edges.size();
 33         G[from].push_back(m - 2);
 34         G[to].push_back(m - 1);
 35     }
 36 
 37     int Maxflow(int s, int t) {
 38         int flow = 0;
 39         for (;;) {
 40             memset(a, 0, sizeof(a));
 41             queue<int> Q;
 42             Q.push(s);
 43             a[s] = INF;
 44             while (!Q.empty()) {
 45                 int x = Q.front(); Q.pop();
 46                 for (int i = 0; i < G[x].size(); i++) {
 47                     Edge& e = edges[G[x][i]];
 48                     if (!a[e.to] && e.cap > e.flow) {
 49                         p[e.to] = G[x][i];
 50                         a[e.to] = min(a[x], e.cap - e.flow);
 51                         Q.push(e.to);
 52                     }
 53                 }
 54                 if (a[t]) break;
 55             }
 56             if (!a[t]) break;
 57             for (int u = t; u != s; u = edges[p[u]].from) {
 58                 edges[p[u]].flow += a[t];
 59                 edges[p[u] ^ 1].flow -= a[t];
 60             }
 61             flow += a[t];
 62         }
 63         return flow;
 64     }
 65 };
 66 
 67 EdmondsKarp g;
 68 
 69 int mp[105][105];
 70 int row[105][105];
 71 int col[105][105];
 72 
 73 int main() {
 74     int T;
 75     scanf("%d", &T);
 76     while (T--) {
 77         int r, c, p;
 78         scanf("%d%d%d", &r, &c, &p);
 79         memset(mp, 0, sizeof(mp));
 80         int x, y;
 81         while (p--) {
 82             scanf("%d%d", &x, &y);
 83             mp[x][y] = 1;
 84         }
 85         scanf("%d", &p);
 86         while (p--) {
 87             scanf("%d%d", &x, &y);
 88             mp[x][y] = 2;
 89         }
 90         memset(row, 0, sizeof(row));
 91         memset(col, 0, sizeof(col));
 92         int cnt = 0;
 93         for (int i = 1; i <= r; i++) {
 94             bool ob = true;
 95             for (int j = 1; j <= c; j++) {
 96                 if (mp[i][j] == 1) {
 97                     if (ob) cnt++;
 98                     row[i][j] = cnt;
 99                     ob = false;
100                 } else if (mp[i][j] == 2) ob = true;
101             }
102         }
103         for (int j = 1; j <= c; j++) {
104             bool ob = true;
105             for (int i = 1; i <= r; i++) {
106                 if (mp[i][j] == 1) {
107                     if (ob) cnt++;
108                     col[i][j] = cnt;
109                     ob = false;
110                 } else if (mp[i][j] == 2) ob = true;
111             }
112         }
113         g.init(cnt + 2);
114         set<int> st;
115         for (int i = 1; i <= r; i++)
116             for (int j = 1; j <= c; j++)
117                 if (row[i][j]) st.insert(row[i][j]);
118         for (set<int>::iterator it = st.begin(); it != st.end();  it++)
119             g.AddEdge(0, *it, 1);
120         st.clear();
121         for (int j = 1; j <= c; j++)
122             for (int i = 1; i <= r; i++)
123                 if (col[i][j]) st.insert(col[i][j]);
124         for (set<int>::iterator it = st.begin(); it != st.end();  it++)
125             g.AddEdge(*it, cnt + 1, 1);
126         for (int i = 1; i <= r; i++)
127             for (int j = 1; j <= c; j++)
128                 if (mp[i][j] == 1) g.AddEdge(row[i][j], col[i][j], 1);
129         printf("%d\n", g.Maxflow(0, cnt + 1));
130     }
131     return 0;
132 }

 

UVa12549 Sentry Robots (二分图最大匹配,最小点集覆盖)

标签:

原文地址:http://www.cnblogs.com/XieWeida/p/5907790.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!