P2055 [ZJOI2009]假期的宿舍 - 二分圖最大匹配
阿新 • • 發佈:2018-10-14
match 二分 ons dfs 的人 clu 數據 自己的 algo
把人和床分開考慮,題目說每個人只能睡和自己直接認識的人的床,就是一種邊的關系,但是並不是人與人,實際上人與人之間連邊是很難處理的,但是如果把人和床連邊,就是一張二分圖,左右兩邊分別是不同的東西,然後求一下最大匹配就好了
沒思路的時候換換角度,看能不能搞出什麽“新東西”來
註意多組數據不超時的情況下能用memset盡量用,有時候感覺某個數組可以不清空但實際上是需要清空的
還有註意連邊的時候沒那麽簡單。。。看註釋吧
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; #define debug(x) cerr << #x << "=" << x << endl; const int MAXN = 210; int n,m,match[MAXN],ans,edge_tot,tot,outnum,last[MAXN],vis[MAXN],gra[MAXN][MAXN],house[MAXN]; int sch[MAXN],t,bad[MAXN]; struct Edge{ int u,v,to; Edge(){} Edge(int u, int v, int to) : u(u), v(v), to(to) {} }e[10010]; inline void add(int u, int v) { e[++edge_tot] = Edge(u, v, last[u]); last[u] = edge_tot; } bool dfs(int x) { for(int i=last[x]; i; i=e[i].to) { int v = e[i].v; if(vis[v]) continue; vis[v] = 1; if(!match[v] || dfs(match[v])) { match[v] = x; return true; } } return false; } int main() { scanf("%d", &t); while(t--) { ans = 0, edge_tot = 0, outnum = 0; memset(match, 0, sizeof(match)); memset(last, 0, sizeof(last)); memset(house, 0, sizeof(house)); memset(sch, 0, sizeof(sch)); scanf("%d", &n); for(int i=1; i<=n; i++) { scanf("%d", &sch[i]); } for(int i=1; i<=n; i++) { int temp_sca = 0; if(sch[i] == 1) scanf("%d", &house[i]); else scanf("%d", &temp_sca), outnum++; if(!house[i] && sch[i]) {//和自己的床連邊,首先i得有床,其次得不回家 outnum++; add(i, i+n); add(i+n, i); } } for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { scanf("%d", &gra[i][j]); if(gra[i][j] && sch[j] && house[i] == 0) { add(i, j+n);//i這個人和j的床位連邊,需要i不是回家的人並且j是有床的(j不一定必須回家) add(j+n, i); } } } for(int i=1; i<=n; i++) { if(!house[i]) { memset(vis, 0, sizeof(vis)); if(dfs(i)) ans++; } } if(ans == outnum) { printf("^_^\n"); } else printf("T_T\n"); } return 0; }
P2055 [ZJOI2009]假期的宿舍 - 二分圖最大匹配