ZJOI2009 假期的宿舍
阿新 • • 發佈:2018-08-31
++ push set 二分圖匹配 getch 過程 getc != 個人
傳送門
這還是很顯然是一道二分圖匹配的題……(看數據範圍辣麽小)
其實這題就是建圖稍微復雜一點。對於每個學生,我們把他們的床連到匯點上,然後對於每個沒回家的和外來的人,我們把他們連到源點上,之後在人和床之間就按給定的關系連上就可以。註意自己和自己的床要連一條邊。
處理過程比較繁瑣……我們可以選擇用1~n表示人,n+1~2*n表示床,其中n+i表示第i個人的床。這樣的話即使有一些人不在校,我們也可以連邊,反正他們和源匯點也不聯通,計算的時候沒什麽關系。
之後直接跑dinic即可。(仍然不會匈牙利)
上代碼。
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<iostream> #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 = 505; const int N = 100005; const int INF = 1e9; typedef longlong 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 from,next,to,v; }e[N]; int t,n,deep[M],g[55][55],bcnt,scnt,ecnt = -1,head[M],cur[M],maxflow,source,sink; bool stu[M],out[M]; queue <int> q; void add(int x,int y,int z) { e[++ecnt].from = x; e[ecnt].to = y; e[ecnt].v = z; e[ecnt].next = head[x]; head[x] = ecnt; } void clear() { memset(stu,0,sizeof(stu)); memset(out,0,sizeof(out)); memset(head,-1,sizeof(head)); memset(cur,-1,sizeof(cur)); ecnt = -1,bcnt = scnt = maxflow = 0; memset(e,0,sizeof(e)); source = 0,sink = 105; } void build() { n = read(); rep(i,1,n) { stu[i] = read(); if(stu[i]) add(i+n,sink,1),add(sink,i+n,0); } rep(i,1,n) { out[i] = read(); if(stu[i] && !out[i]) add(source,i,1),add(i,source,0),scnt++; if(!stu[i]) add(source,i,1),add(i,source,0),scnt++; } rep(i,1,n) rep(j,1,n) { g[i][j] = read(); if(i == j && stu[i] && !out[i]) add(i,i+n,1),add(i+n,i,0); if(g[i][j]) add(i,j+n,1),add(j+n,i,0); } } bool bfs(int s,int t) { memset(deep,-1,sizeof(deep)); while(!q.empty()) q.pop(); rep(i,0,sink+1) cur[i] = head[i]; 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(!limit || s == t) 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(limit,e[i].v)); if(f) { e[i].v -= f,e[i^1].v += f ; flow += f,limit -= f; if(!limit) break; } } if(!flow) deep[s] = -233333; return flow; } void dinic(int s,int t) { while(bfs(s,t)) maxflow += dfs(s,t,INF); } int main() { t = read(); while(t--) { clear(); build(); dinic(source,sink); if(maxflow == scnt) printf("^_^\n"); else printf("T_T\n"); } return 0; }
ZJOI2009 假期的宿舍