题意:有M个女生,N个男生,他们要玩过山车又必须是一男一女一起,女生只愿意和她心中的几位男生坐在一起,问最多能匹配多少对。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2063
——>>刚学了一个二分图的匈牙利算法,但那是一个无向图,编号从1到最后,而题中的是女N人,男M人,编号分别从1开始,这就纳闷了,于是试下将男生编号全部加上女生人数得到男生新编号,没料到不但没TLE,还0ms过,壮哉!
#include <cstdio> #include <vector> #include <cstring> using namespace std; const int maxn = 1000 + 10; vector<int> G[maxn]; bool vis[maxn]; int fa[maxn]; bool dfs(int u) { int d = G[u].size(); for(int i = 0; i < d; i++) { int v = G[u][i]; if(!vis[v]) { vis[v] = 1; int temp = fa[v]; fa[v] = u; if(temp == -1 || dfs(temp)) return 1; fa[v] = temp; } } return 0; } int main() { int K, M, N, i, u, v; while(~scanf("%d", &K)) { if(!K) return 0; for(i = 0; i < maxn; i++) G[i].clear(); scanf("%d%d", &M, &N); int n = M + N; for(i = 0; i < K; i++) { scanf("%d%d", &u, &v); G[u].push_back(v + M); G[v + M].push_back(u); } memset(fa, -1, sizeof(fa)); for(i = 1; i <= n; i++) { memset(vis, 0, sizeof(vis)); dfs(i); } int cnt = 0; for(i = 1; i <= n; i++) if(fa[i] != -1) cnt++; printf("%d\n", cnt/2); } return 0; }
import java.util.Scanner; public class Main { static final int maxn = 1000 + 10; static boolean G[][] = new boolean[maxn][maxn], vis[] = new boolean[maxn]; static int fa[] = new int[maxn], n; public static boolean dfs(int u){ for(int i = 1; i <= n; i++) if(G[u][i] == true && vis[i] == false){ vis[i] = true; int temp = fa[i]; fa[i] = u; if(temp == -1 || dfs(temp) == true) return true; fa[i] = temp; } return false; } public static void main(String[] args) { int K, M, N, i, j; Scanner cin = new Scanner(System.in); while(cin.hasNextInt()){ K = cin.nextInt(); if(K == 0) break; M = cin.nextInt(); N = cin.nextInt(); n = M + N; for(i = 1; i <= n; i++) for(j = 1; j <= n; j++) G[i][j] = false; for(i = 0; i < K; i++){ int u = cin.nextInt(); int v = cin.nextInt(); G[u][v+M] = true; G[v+M][u] = true; } for(i = 1; i <= n; i++) fa[i] = -1; for(i = 1; i <= n; i++){ for(j = 1; j <= n; j++) vis[j] = false; dfs(i); } int cnt = 0; for(i = 1; i <= n; i++) if(fa[i] != -1) cnt++; System.out.println(cnt/2); } cin.close(); } }
2014.5.10,再来(1228KB内存,0MS):
#include <cstdio> #include <cstring> using namespace std; const int maxn = 500 + 10; bool S[maxn], T[maxn]; int M, N, w[maxn][maxn], left[maxn]; bool match(int x) { S[x] = true; for(int i = 1; i <= N; i++) if(w[x][i] && !T[i]) { T[i] = true; if(!left[i] || match(left[i])) { left[i] = x; return true; } } return false; } int main() { int K, G, B; while(scanf("%d", &K) && K) { scanf("%d%d", &M, &N); memset(w, 0, sizeof(w)); for(int i = 0; i < K; i++) { scanf("%d%d", &G, &B); w[G][B] = 1; } memset(left, 0, sizeof(left)); for(int i = 1; i <= M; i++) { memset(S, 0, sizeof(S)); memset(T, 0, sizeof(T)); match(i); } int cnt = 0; for(int i = 1; i <= N; i++) if(left[i]) cnt++; printf("%d\n", cnt); } return 0; }
#include <cstdio> #include <cstring> using namespace std; const int maxn = 500 + 10; bool S[maxn], T[maxn]; int M, N, left[maxn]; int hed[maxn<<1], nxt[maxn<<1], v[maxn<<1], ecnt; void init() { memset(hed, -1, sizeof(hed)); ecnt = 0; } void add_edge(int uu, int vv) { v[ecnt] = vv; nxt[ecnt] = hed[uu]; hed[uu] = ecnt++; } bool match(int x) { S[x] = true; for(int e = hed[x]; e != -1; e = nxt[e]) { int to = v[e]; if(!T[to]) { T[to] = true; if(!left[to] || match(left[to])) { left[to] = x; return true; } } } return false; } int main() { int K, G, B; while(scanf("%d", &K) && K) { scanf("%d%d", &M, &N); init(); for(int i = 0; i < K; i++) { scanf("%d%d", &G, &B); add_edge(G, B); } memset(left, 0, sizeof(left)); for(int i = 1; i <= M; i++) { memset(S, 0, sizeof(S)); memset(T, 0, sizeof(T)); match(i); } int cnt = 0; for(int i = 1; i <= N; i++) if(left[i]) cnt++; printf("%d\n", cnt); } return 0; }