12549 - Sentry Robots (二分图匹配)
来源:互联网 发布:新淘宝店如何破零知乎 编辑:程序博客网 时间:2024/05/17 04:32
该题和HDU 5093 如出一辙 传送门 。即求解二分图最大匹配数 = 最小点集覆盖 。 该题要求用尽量少的机器人看守所有重要的点,并且障碍物会阻隔机器人的看守范围 。
我们不妨将行列分开,按照行和列的最大看守范围编号,这样得到的就是最大匹配数 。 由于要求看守所有重要的点,所以这样可以有效去重,进行了最大匹配之后还可以保证一定看守了所有的点 。 建好图之后套Dinic模板就行了 。
该题有点逆着来的意思 ,请读者仔细品味 。
细节参见代码:
#include<bits/stdc++.h>using namespace std;typedef long long ll;const int INF = 1000000000;const int maxn = 20000 + 100;int T,cnt,n,m,u,pp,a,b,v,w,t,id1[100][100],id2[100][100];char s[maxn][maxn];struct Edge { int from, to, cap, flow;};bool operator < (const Edge& a, const Edge& b) { return a.from < b.from || (a.from == b.from && a.to < b.to);}struct Dinic { int n, m, s, t; vector<Edge> old; vector<Edge> edges; // 边数的两倍 vector<int> G[maxn]; // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号 bool vis[maxn]; // BFS使用 int d[maxn]; // 从起点到i的距离 int cur[maxn]; // 当前弧指针void init(int 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; }}g;char ss[maxn][maxn];map<int,int> p;int main() { scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&pp); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) s[i][j] = '.'; g.init(n*m*2+n); for(int i=1;i<=pp;i++) { scanf("%d%d",&a,&b); s[a][b] = '*'; } scanf("%d",&w); for(int i=1;i<=w;i++) { scanf("%d%d",&a,&b); s[a][b] = '#'; } int cnt = 1; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(s[i][j] == '#') cnt++;//按照行编号 if(s[i][j] == '*') id1[i][j] = cnt; } cnt++; } for(int j=1;j<=m;j++) { for(int i=1;i<=n;i++) { if(s[i][j] == '#') cnt++;//按列编号 if(s[i][j] == '*') id2[i][j] = cnt; } cnt++; } p.clear(); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(s[i][j] == '*') { g.AddEdge(id1[i][j],id2[i][j],1);//连边 if(!p.count(id1[i][j])) { //每个编号只能与源点连一次 p[id1[i][j]] = 1; g.AddEdge(0,id1[i][j],1); } if(!p.count(id2[i][j])) {//同上 p[id2[i][j]] = 1; g.AddEdge(id2[i][j],cnt+1,1); } } } } int ans = g.Maxflow(0,cnt+1); printf("%d\n",ans); } return 0;}
1 1
- 12549 - Sentry Robots (二分图匹配)
- Uva 12549 Sentry Robots 网络流 - 二分图匹配
- uva 12549 Sentry Robots 最大二分匹配
- 【uva 12549】Sentry Robots HDU 2119 (hdu 2119Matrix升级版) 最小点覆盖+二分图匹配
- ACM->uvalive->Sentry Robots(二分图匹配的最小点覆盖)
- [二分图最大匹配=最小覆盖点]uva12549 Sentry Robots
- Sentry Robots, ACM/ICPC SWERC 2012, UVa12549 【二分图】
- UVA 12549(p381)----Sentry Robots
- zoj 1654 Place the Robots (二分图匹配)
- ZOJ1654-Place the Robots(二分图匹配)
- Sentry Robots
- ZOJ1654 place the robots(二分图匹配)
- 【二分图匹配】zoj1654Place the Robots
- ZOJ1654 Place the Robots (二分图匹配)
- ZOJ 1654 Place the Robots建图思维(分块思想)+二分匹配
- zoj 1654 Place the Robots(二分图匹配 匈牙利算法)
- ZOJ 1654 Place the Robots(二分图最大匹配)
- zoj 1654 Place the Robots (二分图匹配)
- makefile分层目录结构
- 八皇后问题(bjfu 1275)
- Android UI设计:shape
- Polyfill
- 数据持久化-属性列表、归档、NSUserDefaults
- 12549 - Sentry Robots (二分图匹配)
- oc MRC内存管理机制alloc/retain/copy/release/autorelease
- Android UI设计——GridView控件
- JQuery 弹出层,始终显示在屏幕正中间
- 你是我的小呀小苹果——苹果ios编程第一课
- 异步模式下的Ajax的同步问题
- easyui 时间控件包含时分
- 【转】RGB颜色查询对照表
- Pthread_Mutex_t Vs Pthread_Spinlock_t (转载)