P2055 [ZJOI2009]假期的宿舍
阿新 • • 發佈:2018-07-23
結果 代碼 不知道 next 宿舍 pre strong turn 不一定
有點燒腦。。。
這道題是求二分圖完美匹配。沒看請題意還不知道是求完美匹配,結果爆零。
人一共分三種:
在校學生 && 回家。這類人擁有一個床,但是不睡。
在校學生 && 不回家。這類人擁有一個床,但也要睡一個床。有時不一定睡自己的。
外來學生。這類人沒床卻想睡覺。
顯然要用\(2n\)的空間來建立人和床。
等待匹配的人只有1、3兩種情況,等待匹配的床只有1、2兩種情況。
第1種情況連床沒什麽卵用。又不睡。
只有第2種情況的人可以連自己的床。
第3種情況的人一定要睡別人的床。
在2、3種情況中,只要認識的人有床,就可以連接。
然後套個二分圖匹配的樣子,跑跑網絡流就ok了。
最後判斷答案是不是等於人數,輸出那兩個表情即可。
代碼:
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> const int maxn = 1005, INF = 19260817; struct Edges { int next, to, weight; } e[1000005]; int head[maxn], tot;// remember to set tot = 1 int n, s, t; bool in_school[maxn], go_home[maxn]; int dep[maxn], cur[maxn]; void link(int u, int v, int w) { e[++tot] = (Edges){head[u], v, w}; head[u] = tot; } void addEdges(int u, int v, int w) { link(u, v, w); link(v, u, 0); } int read() { int ans = 0; char ch = getchar(); while(ch > ‘9‘ || ch < ‘0‘) ch = getchar(); while(ch >= ‘0‘ && ch <= ‘9‘) { ans = ans * 10 + ch - ‘0‘; ch = getchar(); } return ans; } bool bfs() { memset(dep, 0, sizeof(dep)); std::queue<int> q; dep[s] = 1; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); for(int i = head[u]; i; i = e[i].next) { int v = e[i].to; if(!dep[v] && e[i].weight > 0) { dep[v] = dep[u] + 1; q.push(v); } } } return dep[t]; } int dfs(int u, int flow) { if(u == t) return flow; for(int &i = cur[u]; i; i = e[i].next) { int v = e[i].to; if(dep[v] == dep[u] + 1 && e[i].weight > 0) { int di = dfs(v, std::min(e[i].weight, flow)); if(di > 0) { e[i].weight -= di; e[i ^ 1].weight += di; return di; } } } return 0; } int dinic() { int ans = 0; while(bfs()) { for(int i = 1; i <= t; i++) cur[i] = head[i]; while(int temp = dfs(s, INF)) ans += temp; } return ans; } int main() { int T = read(); while(T--) { // how to define nodes? // [1, n] person // [n + 1, n + n] beds // not go home->need bed // only do in-school students have beds // not in-school students->the persons visiting // go home->never consider them tot = 1; memset(head, 0, sizeof(head)); memset(e, 0, sizeof(e)); n = read(); int cnt = 0; s = n + n + 1; t = s + 1; for(int i = 1; i <= n; i++) in_school[i] = read(); for(int i = 1; i <= n; i++) go_home[i] = read(); for(int i = 1; i <= n; i++) { addEdges(s, i, 1); addEdges(n + i, t, 1); if((in_school[i] && !go_home[i]) || !in_school[i]) cnt++; } for(int i = 1; i <= n; i++) { if(in_school[i] && !go_home[i]) addEdges(i, n + i, 1); for(int j = 1; j <= n; j++) { int temp = read(); if(temp && in_school[j] && !(in_school[i] && go_home[i])) addEdges(i, n + j, 1); } } int ans = dinic(); if(ans == cnt) printf("^_^\n"); else printf("T_T\n"); } return 0; }
P2055 [ZJOI2009]假期的宿舍