都是一些很裸的二分图最大匹配.
纯当复习了.
POJ 1274
#include<cstdio> #include<cstring> #include<vector> #include<iostream> using namespace std; #define bug(s) cout<<#s<<"="<<s<<" " inline int Rint() {int x; scanf("%d", &x); return x;} #define MAXN 500 vector<int> G[MAXN]; int vis[MAXN]; int flag[MAXN]; //0-未盖 / 对应点-已盖 int n, m; int dfs(int u) { for(int i=0; i<(int)G[u].size(); i++) { int v = G[u][i]; if(!vis[v]) //未访问 { vis[v] = 1; if(!flag[v] || dfs(flag[v])) //!!不是dfs(v) -> dfs(flag[v]) 对应点 { flag[v] = u; return 1; } } } return 0; } int hungary() { memset(flag, 0, sizeof(flag)); int ans=0; for(int i=1; i<=n; i++) //集合X中点 1~m { memset(vis, 0, sizeof(vis)); if(dfs(i)) ans++; } return ans; } void print_ans() //输出匹配M { for(int i=n+1; i<=n+n; i++) //flag[v]=u...v=m+1~n if(flag[i]) //v为盖点,输出对应的匹配边 { printf("%d->%d\n", flag[i], i); } } int main() { while(scanf("%d%d", &n, &m)==2) { for(int i=1; i<=n; i++) { if(!G[i].empty()) G[i].clear(); } for(int i=1; i<=n; i++) { //bug(i); int v; char ch; int cnt = Rint(); while(cnt--) { v = Rint(); //bug(v); G[i].push_back(v+n); //if(ch == '\n') break; } //cout<<endl; } printf("%d\n", hungary()); //print_ans(); } //read_graph(); //printf("%d\n", hungary()); //print_ans(); }
#include<cstdio> #include<cstring> #include<iostream> #include<cmath> #include<string> #include<vector> #include<map> #include<algorithm> using namespace std; inline int Rint() { int x; scanf("%d", &x); return x; } inline int max(int x, int y) { return (x>y)? x: y; } inline int min(int x, int y) { return (x<y)? x: y; } #define FOR(i, a, b) for(int i=(a); i<=(b); i++) #define FORD(i,a,b) for(int i=(a);i>=(b);i--) #define REP(x) for(int i=0; i<(x); i++) typedef long long int64; #define INF (1<<30) #define bug(s) cout<<#s<<"="<<s<<" " #define MAXN 400 #define MAXM MAXN*MAXN //int G[MAXN][MAXN]; //{U}->{V} int fa[MAXM], next[MAXM], u[MAXM], v[MAXM], w[MAXM], idx; //边集数组前向星, 表头后面只能跟边, 因为若跟点无法确定下一个点信息 int flag[MAXN]; //盖, flag[{V}] = {U} int vis[MAXN]; //dfs访问标记, 只对V int n, m; void addedge(int tu, int tv, int tw) { u[idx] = tu; v[idx] = tv; w[idx] = tw; next[idx] = fa[tu]; fa[tu] = idx++; } int dfs(int tu) { //vis[u] = 1; for(int e = fa[tu]; e!=-1; e = next[e]) { int tv = v[e]; if(vis[tv]) continue; vis[tv] = 1; if(!flag[tv] || dfs(flag[tv])) { //bug(v);bug(u)<<endl; flag[tv] = tu; return 1; } } return 0; } int hungry() { int ans = 0; memset(flag, 0, sizeof(flag)); //清空盖点 FOR(i, 1, n) //每次从U出发, 找未盖的V点 or 增广路 { memset(vis, 0, sizeof(vis)); if(dfs(i)) ans++; } return ans; } int main() { int T = Rint(); while(T--) { scanf("%d%d", &n, &m); // n门课, m个学生 idx = 0; memset(fa, -1, sizeof(fa)); //memset(G, 0, sizeof(G)); FOR(i, 1, n) { int cnt = Rint(); while(cnt--) { int tv = Rint(); //G[i][v] = 1; addedge(i, tv, 1); } } printf("%s\n", hungry() == n? "YES": "NO"); } }
这题只要把(星期, 班级)对, hash一下.就行
#include<cstdio> #include<cstring> #include<iostream> #include<cmath> #include<string> #include<vector> #include<map> #include<algorithm> using namespace std; inline int Rint() { int x; scanf("%d", &x); return x; } inline int max(int x, int y) { return (x>y)? x: y; } inline int min(int x, int y) { return (x<y)? x: y; } #define FOR(i, a, b) for(int i=(a); i<=(b); i++) #define FORD(i,a,b) for(int i=(a);i>=(b);i--) #define REP(x) for(int i=0; i<(x); i++) typedef long long int64; #define INF (1<<30) #define bug(s) cout<<#s<<"="<<s<<" " #define MAXN 1000 #define MAXM MAXN*MAXN //int G[MAXN][MAXN]; //{U}->{V} int fa[MAXM], next[MAXM], u[MAXM], v[MAXM], w[MAXM], idx; //边集数组前向星, 表头后面只能跟边, 因为若跟点无法确定下一个点信息 int flag[MAXN]; //盖, flag[{V}] = {U} int vis[MAXN]; //dfs访问标记, 只对V int n, m; void addedge(int tu, int tv, int tw) { u[idx] = tu; v[idx] = tv; w[idx] = tw; next[idx] = fa[tu]; fa[tu] = idx++; } int dfs(int tu) { //vis[u] = 1; for(int e = fa[tu]; e!=-1; e = next[e]) { int tv = v[e]; if(vis[tv]) continue; vis[tv] = 1; if(!flag[tv] || dfs(flag[tv])) { //bug(v);bug(u)<<endl; flag[tv] = tu; return 1; } } return 0; } int hungry() { int ans = 0; memset(flag, 0, sizeof(flag)); //清空盖点 FOR(i, 1, n) //每次从U出发, 找未盖的V点 or 增广路 { memset(vis, 0, sizeof(vis)); if(dfs(i)) ans++; } return ans; } int main() { //int T = Rint(); while(scanf("%d", &n) == 1) // n门课, m天 { idx = 0; memset(fa, -1, sizeof(fa)); //memset(G, 0, sizeof(G)); FOR(i, 1, n) { int cnt = Rint(); while(cnt--) { int tv = Rint(); int cs = Rint(); //G[i][v] = 1; //addedge(i, (tv-1)*7+cs, 1); addedge(i, (tv-1)*12+cs, 1); // 把(天, 班级) 哈希即可. } } printf("%d\n", hungry()); } }