二分+最大流,处理关系的时候使用并查集会比较好,建图简单,忽略
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define MAXVERTEX 512
#define INF 0x7fffffff
using namespace std;
typedef struct $edge {
int x, y;
}Edge;
Edge edge_arr[MAXVERTEX*MAXVERTEX];
int used[MAXVERTEX][MAXVERTEX];
int root[MAXVERTEX], residual[MAXVERTEX][MAXVERTEX], end_vertex;
int pre[MAXVERTEX], cur[MAXVERTEX], dis[MAXVERTEX], gap[MAXVERTEX];
int get_root(int x)
{
if( x == root[x] ) return x;
return root[x] = get_root(root[x]);
}
void make_graph(int m, int arc, int vertex)
{
int f, t;
memset(residual, 0, sizeof(residual));
for(int i = 1; i <= vertex; i ++)
residual[end_vertex-1][i] = m;
for(int i = vertex+1; i < end_vertex-1; i ++)
residual[i][end_vertex] = m;
for(int i = 0; i < arc; i ++) {
f = edge_arr[i].x; t = edge_arr[i].y; residual[f][t] = 1;
for(int j = 1; j <= vertex; j ++) {
if( root[f] == root[j]) residual[j][t] = 1;
}
}
}
int i_sap(int source, int sink)
{
int u(source), v, min_dist, max_flow(0), path_flow(INF);
memset(dis, 0, sizeof(dis));
memset(gap, 0, sizeof(gap));
memset(cur, 0, sizeof(cur));
gap[0] = sink; cur[source] = pre[source] = source;
while( dis[source] < sink ) {
loop:
for(v = cur[u]; v <= sink; v ++) {
if( !residual[u][v] || (dis[u] != dis[v]+1) ) continue;
pre[v] = u; path_flow = min(path_flow, residual[u][v]);
cur[u] = v; u = v;
if( v == sink ) {
for(u = pre[u]; v != source; v = u, u = pre[u]) {
residual[u][v] -= path_flow; residual[v][u] += path_flow;
}
max_flow += path_flow; path_flow = INF;
}
goto loop;
}
min_dist = sink;
for(v = 1; v <= sink; v ++) {
if( residual[u][v] && (min_dist > dis[v]) ) {
cur[u] = v; min_dist = dis[v];
}
}
gap[dis[u]] --;
if( !gap[dis[u]] ) break;
dis[u] = min_dist+1;
gap[dis[u]] ++; u = pre[u];
}
//printf("max_flow = %d\n", max_flow);
return max_flow;
}
int main(int argc, char const *argv[])
{
//freopen("test.in", "r", stdin);
int cnt, vertex, arc, match, l, r, m, x, y, r_x, r_y, ans;
scanf("%d", &cnt);
while( cnt-- ) {
scanf("%d %d %d", &vertex, &arc, &match);
end_vertex = (vertex<<1)+2;
for(int i = 0; i < arc; i ++) {
scanf("%d %d", &edge_arr[i].x, &edge_arr[i].y);
edge_arr[i].y += vertex;
}
for(int i = 0; i <= end_vertex; i ++)
root[i] = i;
for(int i = 0; i < match; i ++) {
scanf("%d %d", &x, &y);
r_x = get_root(x); r_y = get_root(y);
if( r_x != r_y ) root[r_x] = r_y;
}
for(int i = 0; i <= end_vertex; i ++)
root[i] = get_root(i);
l = 1, r = vertex, ans = 0;
while( l <= r ) {
m = (l+r)>>1; make_graph(m, arc, vertex);
if( m*vertex == i_sap(end_vertex-1, end_vertex) ) {
ans = m; l = m+1;
}
else
r = m-1;
}
printf("%d\n", ans);
}
return 0;
}