题目大意就是有n对男女,玩儿结婚游戏,要求就是开始每个女生心目中都会有几个心仪的男生,同时呢,好友(girl)心仪的男生也是可以选做自己的boyfriend。每一轮游戏男女配对(只和心仪的)且不于之前配对过的配对,问最多可以玩儿几轮这样的游戏。
男女配对显然是二分图,然后就是二分次数k,k必然是大于1而小于n+1的。
/***************************************** Author :Crazy_AC(JamesQi) Time :2015 File Name : *****************************************/ // #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <algorithm> #include <iomanip> #include <sstream> #include <string> #include <stack> #include <queue> #include <deque> #include <vector> #include <map> #include <set> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <climits> using namespace std; #define MEM(x,y) memset(x, y,sizeof x) #define pk push_back typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; typedef pair<ii,int> iii; const double eps = 1e-10; const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int N = 110; int g[N][N]; int n, m, f; int F[N]; int Find(int x) {return F[x] == -1?x:F[x] = Find(F[x]);} void input() { memset(g, 0,sizeof g); scanf("%d%d%d",&n,&m,&f); int u, v; for (int i = 1;i <= m;++i) { scanf("%d%d",&u,&v); g[u][v] = 1; } memset(F, -1,sizeof F); for (int i = 1;i <= f;++i) { scanf("%d%d",&u,&v); int t1 = Find(u),t2 = Find(v); if (t1 != t2) F[t1] = t2; } for (int i = 1;i <= n;++i) { for (int j = 1;j <= n;++j) { int t1 = Find(i),t2 = Find(j); if (t1 == t2) { for (int k = 1;k <= n;++k) g[i][k] |= g[j][k]; } } } } int head[N*3], pnt[N*1000], nxt[N*1000], cap[N*1000], flow[N*1000]; int cnt; int cur[N*3]; int dis[N*3]; void addedge(int u,int v,int can) { pnt[cnt] = v,cap[cnt] = can, flow[cnt] = 0; nxt[cnt] = head[u], head[u] = cnt++; pnt[cnt] = u,cap[cnt] = 0,flow[cnt] = 0; nxt[cnt] = head[v], head[v] = cnt++; } bool bfs(int s,int t) { queue<int> que; que.push(s); memset(dis, -1,sizeof dis); dis[s] = 0; while(!que.empty()) { int u = que.front(); que.pop(); for (int i = head[u];i!=-1;i = nxt[i]) { if (dis[pnt[i]] == -1 && cap[i] > flow[i]) { dis[pnt[i]] = dis[u] + 1; que.push(pnt[i]); } } } return dis[t] != -1; } int dfs(int u,int a,int t) { if (u == t || a == 0) return a; int sum = 0; for (int &i = cur[u];~i;i = nxt[i]) { int v = pnt[i]; int f; if (dis[v] == dis[u] + 1 && (f = dfs(v, min(a, cap[i] - flow[i]), t)) > 0) { sum += f; flow[i] += f; flow[i^1] -= f; a -= f; if (a == 0) break; } } return sum; } int MaxFlow(int s,int t) { int sum = 0; while(bfs(s, t)) { memcpy(cur, head, sizeof head); sum += dfs(s, INF, t); } return sum; } void getmap(int mid) { memset(head, -1,sizeof head); cnt = 0; int s = 0, t = n*2+1; for (int i = 1;i <= n;++i) { addedge(s, i, mid); addedge(i + n, t, mid); for (int j = 1;j <= n;++j) { if (g[i][j]) addedge(i, j+n, 1); } } } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int t; scanf("%d",&t); while(t--) { input(); int low = 1,high = n + 1; int ans = -1; while(low < high) { int mid = (low + high) / 2; getmap(mid); int tmp = MaxFlow(0,n*2+1); if (tmp == n*mid) { low = mid + 1; }else high = mid; } printf("%d\n", low - 1); } return 0; }