Gym 100203I I WIN(最大流)
来源:互联网 发布:sql 表 设计 编辑:程序博客网 时间:2024/05/22 06:13
题意:有一个由字母w,i,n组成的矩阵,问这个矩阵中最多能找到多少个没有覆盖的win(可以是直线型或者L型)。
思路:最大流。将源点与所有的w连一条容量为1的边,将所有n与汇点连一条容量为1的边,将每个字母i拆成两个点之间连一条容量为1的边,然后就是根据原图建立新边,答案就是最大流。
#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<iostream>#include<algorithm>#include<vector>#include<map>#include<queue>#include<stack>#include<string>#include<map>#include<set>#include<ctime>#define eps 1e-6#define LL long long#define pii pair<int, int>//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;//最大流//Dinic算法求最大流,一般效率很高//s源点,t汇点,g,e全局变量,表示存边的邻接表const int INF = 1000000000;const int MAXN = 4000, MAXM = 500000;//最大的点数和边数const int DX[] = {-1, 0, 1, 0};const int DY[] = {0, -1, 0, 1};struct Edge{ int to, next, cap;} edge[MAXM*2];int n, s, t;int head[MAXN], tot;void addedge(int u, int v, int w){ edge[tot].to = v; edge[tot].cap = w; edge[tot].next = head[u]; head[u] = tot++; edge[tot].to = u; edge[tot].cap = 0; edge[tot].next = head[v]; head[v] = tot++;}void init(){ memset(head, -1, sizeof(head)); tot = 0;}queue<int> q;bool vis[MAXN];int dist[MAXN];void bfs(){ memset(dist, 0, sizeof(dist)); while(!q.empty()) q.pop(); vis[s] = 1; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); for(int i = head[u]; i!=-1; i=edge[i].next) { if(!edge[i].cap || vis[edge[i].to]) continue; q.push(edge[i].to); vis[edge[i].to] = 1; dist[edge[i].to] = dist[u] + 1; } }}int dfs(int u, int a){ if(u==t) return a; int ret = 0; for(int i = head[u]; a&&i!=-1; i = edge[i].next) { if(edge[i].cap && dist[u]+1==dist[edge[i].to]) { int tmp = dfs(edge[i].to, min(a, edge[i].cap)); edge[i].cap -= tmp; edge[i^1].cap += tmp; a -= tmp; ret += tmp; } } return ret;}int maxflow(){ int ret = 0; while(true) { memset(vis, 0, sizeof(vis)); bfs(); if(!vis[t]) return ret; ret += dfs(s, INF); }}char G[50][50];int id[50][50];int main(){ //freopen("input.txt", "r", stdin);//freopen("output2.txt", "w", stdout);int row, col;while(cin >> row >> col) { init(); int cntW = 0, cntI = 0, cntN = 0; for(int i = 1; i <= row; i++) { scanf("%s", G[i]+1); for(int j = 1; j <= col; j++) { if(G[i][j] == 'W') cntW++; else if(G[i][j] == 'I') cntI++; else cntN++; } } int tmp1 = 0, tmp2 = 0, tmp3 = 0; for(int i = 1; i <= row; i++) for(int j = 1; j <= col; j++) { if(G[i][j] == 'W') id[i][j] = ++tmp1; else if(G[i][j] == 'I') id[i][j] = ++tmp2; else id[i][j] = ++tmp3; } for(int i = 1; i <= row; i++) { for(int j = 1; j <= col; j++) { if(G[i][j] == 'W') { for(int k = 0; k < 4; k++) { int nx = i + DX[k], ny = j + DY[k]; if(nx<1 || nx>row || ny<1 || ny>col) continue; if(G[nx][ny] == 'I') addedge(1+id[i][j], 1+cntW+id[nx][ny], 1); } } else if(G[i][j] == 'N') { for(int k = 0; k < 4; k++) { int nx = i + DX[k], ny = j + DY[k]; if(nx<1 || nx>row || ny<1 || ny>col) continue; if(G[nx][ny] == 'I') addedge(1+cntW+cntI+id[nx][ny], 1+cntW+cntI+cntI+id[i][j], 1); } } } } n = cntW + 2*cntI + cntN + 2; s = 1, t = n; for(int i = 1; i <= cntI; i++) addedge(1+cntW+i, 1+cntW+cntI+i, 1); for(int i = 1; i <= cntW; i++) addedge(1, i+1, 1); for(int i = 1; i <= cntN; i++) addedge(1+cntW+cntI+cntI+i, n, 1); int ans = maxflow(); cout << ans << endl;} return 0;}
0 0
- Gym 100203I I WIN(最大流)
- Gym - 100203I I WIN 网络流
- Gym 100942I Manhattan Project (set)
- GYM 100247 I. Meteor Flow(贪心)
- GYM 100030 I.Prohibition(贪心)
- GYM 100488 I.Map Coloring(水~)
- GYM 100883 I.Teleportia(Floyd)
- GYM 101102 I.Simple Robot(水~)
- gym 100947I (求因子)
- CodeForces Gym 100735I
- Mirrored String I Gym
- Gym 101147.I
- Gym 101164.I
- Gym 101243.I
- Gym 101482. I
- Gym 101623I
- I persist,I win!--Cru
- I - In Touch-Gym 100492I-水题
- 4408: [Fj Winter Camp 2016]神秘数&&4299: Codechef FRBSUM|主席树
- 算法代码实现之冒泡排序,C/C++ 实现
- Json数据格式解析·编译器观点
- [NOIP 2011] Mayan游戏
- 操作系统
- Gym 100203I I WIN(最大流)
- Simple Breaking Waves in Maya
- Android Camera Subsystem 架构(Binder机制)及显示分析
- (转)计算几何算法大全
- 对javascript中闭包概念的理解
- CodeForces 610 B. Vika and Squares(水~)
- 2016.2.26 ACM讨论群群赛 ABCDEF
- String,StringBuffer与StringBuilder的区别??
- 3dmax中的UVW 贴图修改器详解(史上最全)