您的位置:首页 > 其它

Zoj 3646 Matrix Transformer 二分图完美匹配

2015-09-09 23:02 381 查看
题目大意:给你一个n * n 的二维图, 每个点都有一个方向, 上或者下, 用U和D表示, 蓝厚问你交换任意次整行后, 能不能让主对角线上全部都是U。

第一眼一看, 水题啊贪心搞一搞就行了啊,然后写到一半发现并不能随意水过去, 情况太多了Orz, 然后就想,难道是网络流,,当时一直以为有更简单的解法可是赶时间懒得想就直接dinic上去干了,,后来发现这题真是网络流, 每个U点的行和列对应点连边, 源点与横坐标连边, 汇点跟纵坐标连边, 然后跑一边最大流看流量是否能等于n就行。

#include <set>

#include <map>

#include <queue>

#include <stack>

#include <cmath>

#include <string>

#include <cctype>

#include <cstdio>

#include <vector>

#include <cstdlib>

#include <cstring>

#include <iomanip>

#include <sstream>

#include <iostream>

#include <algorithm>

using namespace std;

#define ls id<<1,l,mid

#define rs id<<1|1,mid+1,r

#define OFF(x) memset(x,-1,sizeof x)

#define CLR(x) memset(x,0,sizeof x)

#define MEM(x) memset(x,0x3f,sizeof x)

typedef long long ll ;

typedef pair<int,int> pii ;

const int maxm = 1e5+50 ;

const int maxn = 500 ;

const int inf = 0x3f3f3f3f ;

const int MOD = 1e9+7 ;

int pnt[maxm], nxt[maxm], cap[maxm];

int head[maxn], vis[maxn], cnt, ed,L[maxn], n;

char s[250][250];

int dfs(int u, int f) {

if (u == ed) return f;

int left = f;

for (int i = head[u]; ~i; i = nxt[i]) {

int v = pnt[i];

if (cap[i] <= 0 || L[v] != L[u] + 1) continue ;

int d = dfs(v, min(left, cap[i]));

if (d > 0) {

cap[i] -= d;

cap[i ^ 1] += d;

left -= d;

if (left == 0) break;

} else L[v] = 0;

}

return f - left;

}

bool bfs() {

CLR(L);

queue<int> q;

q.push(0);

L[0] = 1;

while (q.size()) {

int u = q.front();q.pop();

for (int i = head[u]; ~i; i = nxt[i]) {

int v = pnt[i];

if (L[v] || cap[i] <= 0) continue ;

L[v] = L[u] + 1;

q.push(v);

// printf("%d\n",v);

}

}

return L[ed];

}

int Max_Flow() {

int res = 0;

while (bfs()) {

// puts("**");

res += dfs(0, inf);

}

return res;

}

void add_edge(int u, int v, int w) {

pnt[cnt] = v;

nxt[cnt] = head[u];

cap[cnt] = w;

head[u] = cnt++;

}

void add_edges(int u, int v, int w) {

add_edge(u, v, w);

add_edge(v, u, 0);

}

int main () {

#ifdef LOCAL

freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);

// freopen("C:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);

#endif

while (~scanf("%d", &n)) {

ed = n * 2 + 1;

OFF(head);cnt = 0;

for (int i = 1; i <= n; i++) scanf("%s", s[i] + 1);

for (int i = 1; i <= n; i++) {

add_edges(0, i, 1);

add_edges(n + i, ed, 1);

for (int j = 1; j <= n; j++) {

if (s[i][j] == 'U') add_edges(i, j + n, 1);

}

}

bool flag = Max_Flow() == n;

// cout << flag << "\n" ;

if (flag) puts("YES");

else puts("NO");

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: