1. 程式人生 > >ZJOI2007 矩陣遊戲

ZJOI2007 矩陣遊戲

getch per ace href sin 要求 size push oid

傳送門

這道題就是一道不大容易被看出來的二分圖匹配……(也可能是我太菜了qaq)

首先我們看一下,題目要求我們把對角線上都填滿。我們把每一行和每一列都抽象成一個點,那麽我們只要讓每一行和每一列都匹配上就可以。

先把每行向源點連邊,每列向匯點連邊,行和列之間,如果g[i][j]是1的話那麽就把第i行和第j列之間連邊。我們想象一下,交換某兩行或者某兩列之後,其實連邊的情況並沒有發生變化,也就是說,最大匹配數無論怎麽交換都不會發生改變。

所以只要在最開始的圖上跑一遍dinic求最大匹配即可,如果其等於n說明可以,否則不行。

#include<cstdio>
#include<algorithm>
#include
<cstring> #include<cmath> #include<queue> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar(‘\n‘) using namespace std; const int M = 1005; const int N = 100005; const int INF = 1e9; typedef long long ll; int read() {
int ans = 0,op = 1; char ch = getchar(); while(ch < 0 || ch > 9) { if(ch == -) op = -1; ch = getchar(); } while(ch >= 0 && ch <= 9) { ans *= 10; ans += ch - 0; ch = getchar(); } return ans * op; } struct
node { int next,to,from,v; }e[N]; int t,n,deep[M],source,sink,a,head[M],cur[M],ecnt = -1,maxflow; queue <int> q; void clear() { memset(head,-1,sizeof(head)); memset(cur,-1,sizeof(cur)); ecnt = -1,maxflow = 0; source = 0,sink = 401; memset(e,0,sizeof(e)); } void add(int x,int y,int z) { e[++ecnt].to = y; e[ecnt].from = x; e[ecnt].v = z; e[ecnt].next = head[x]; head[x] = ecnt; } bool bfs(int s,int t) { memset(deep,-1,sizeof(deep)); rep(i,0,sink+1) cur[i] = head[i]; while(!q.empty()) q.pop(); deep[s] = 0,q.push(s); while(!q.empty()) { int k = q.front();q.pop(); for(int i = head[k];i != -1;i = e[i].next) { if(deep[e[i].to] == -1 && e[i].v) deep[e[i].to] = deep[k] + 1,q.push(e[i].to); } } if(deep[t] == -1) return 0; else return 1; } int dfs(int s,int t,int limit) { if(s == t || !limit) return limit; int flow = 0; for(int i = cur[s];i != -1;i = e[i].next) { cur[s] = i; if(deep[e[i].to] != deep[s] + 1) continue; int f = dfs(e[i].to,t,min(e[i].v,limit)); if(f) { e[i].v -= f,e[i^1].v += f; flow += f,limit -= f; if(!limit) break; } } if(!flow) deep[s] = -2333333; return flow; } void dinic(int s,int t) { while(bfs(s,t)) maxflow += dfs(s,t,INF); } int main() { t = read(); while(t--) { clear(); n = read(); rep(i,1,n) add(source,i,1),add(i,source,0),add(i+n,sink,1),add(sink,i+n,0); rep(i,1,n) rep(j,1,n) { a = read(); if(a) add(i,j+n,1),add(j+n,i,0); } dinic(source,sink); if(maxflow == n) printf("Yes\n"); else printf("No\n"); } return 0; }

ZJOI2007 矩陣遊戲