UVA_753
我们可以把适配器看做一条有向边,而插头和插座分别看成两个点,同时引入一个源点与devices相连,引入一个汇点与receptacles相连,同时由于适配器是无限量的,所以适配器这条有向边的边权为INF,而源点与devices相连的以及receptacles和汇点相连的有向边的边权为1。
建好图后求源点到汇点的最大流即可,然后用m减去最大流就是最终结果。
但其实,适配器作用实际上就是将device和相应的receptacle连接起来,因此,我们可以用Floyd根据当前适配器的种类求出每个device所能够直接或间接连接的receptacle,这样我们只要用匈牙利算法求一个二分图最大匹配即可。
(下面的程序是用网络流算法写的)
#include<stdio.h>
#include<string.h>
#define MAXD 510
#define MAXN 110
#define MAXM 1010
#define INF 1000000000
char str[30], st[MAXD][30], name[MAXN][30], plug[MAXN][30];
int N, M, K, size, e, first[MAXD], v[MAXM], next[MAXM];
int flow[MAXM], d[MAXD], work[MAXD], q[MAXD];
void add(int x, int y, int f)
{
v[e] = y;
flow[e] = f;
next[e] = first[x];
first[x] = e;
e ++;
}
void init()
{
int i, j, x, y;
e = 0;
size = 2;
memset(first, -1, sizeof(first));
scanf("%d", &N);
for(i = 0; i < N; i ++)
{
scanf("%s", st[size]);
add(size, 1, 1);
add(1, size, 0);
size ++;
}
scanf("%d", &M);
for(i = 1; i <= M; i ++)
scanf("%s%s", name[i], plug[i]);
scanf("%d", &K);
for(i = 0; i < K; i ++)
{
scanf("%s", str);
for(x = 2; x < size; x ++)
if(strcmp(str, st[x]) == 0)
break;
if(x == size)
{
strcpy(st[size], str);
size ++;
}
scanf("%s", str);
for(y = 2; y < size; y ++)
if(strcmp(str, st[y]) == 0)
break;
if(y == size)
{
strcpy(st[size], str);
size ++;
}
add(x, y, INF);
add(y, x, 0);
}
for(i = 1; i <= M; i ++)
{
for(x = 2; x < size; x ++)
if(strcmp(plug[i], st[x]) == 0)
break;
if(x != size)
{
add(0, size + i, 1);
add(size + i, 0, 0);
add(size + i, x, 1);
add(x, size + i, 0);
}
}
}
int bfs()
{
int i, j, rear;
memset(d, -1, sizeof(d));
d[0] = 0;
rear = 0;
q[rear ++] = 0;
for(i = 0; i < rear; i ++)
for(j = first[q[i]]; j != -1; j = next[j])
if(flow[j] && d[v[j]]== -1)
{
d[v[j]] = d[q[i]] + 1;
if(v[j] == 1)
return 1;
q[rear ++] = v[j];
}
return 0;
}
int dfs(int cur, int a)
{
if(cur == 1)
return a;
for(int &i = work[cur]; i != -1; i = next[i])
if(flow[i] && d[v[i]] == d[cur] + 1)
if(int t = dfs(v[i], flow[i] < a ? flow[i] : a))
{
flow[i] -= t;
flow[i ^ 1] += t;
return t;
}
return 0;
}
int dinic()
{
int t, res = 0;
while(bfs())
{
memcpy(work, first, sizeof(first));
while(t = dfs(0, INF))
res += t;
}
return res;
}
int main()
{
int i, T;
scanf("%d", &T);
for(i = 0; i < T; i ++)
{
init();
if(i)
printf("\n");
int res = dinic();
printf("%d\n", M - res);
}
return 0;
}