HDU_1853

首先,如果要保证图有环,并且环之间没有交点的话,那么必然每个点的出度和入度都应为1,因此我们可以把一个点拆成两个点,分别表示出度及入度,然后去找拆点后构成的二分图的完美匹配。

对于怎么判断原图是否能构成完美匹配,我暂时想到了两个思路:

①在用KM算法之前先用匈牙利算法求最大匹配,如果最大匹配数为N,那么就一定会存在完美匹配。

②我们可以从KM算法的slack变量入手,每一次更新slack,都是在尝试进行新一轮的增广,并且会把更多的原本不在交错树中的点加入进来,当把所有可以加到交错树中点都加入之后,slack就不会再进行更新。换句话讲,如果slack不再更新,那么一定是把所有可以加到交错树中的点都已经加入了,并且这个时候依然不能找到增广路。因此,当slack不再更新的时候我们就可以断定原图不能构成完美匹配了。当然这么做的前提是,我们需要把slack放到for(;;)的里面去,并且每次尝试增广之前,都初始化成INF

#include<stdio.h>
#include<string.h>
#define MAXD 110
#define INF 1000000000
#define MAX 1001
int yM[MAXD], visy[MAXD], visx[MAXD];
int G[MAXD][MAXD], N, M, A[MAXD], B[MAXD], slack;
void init()
{
int i, a, b, temp;
memset(G, 0, sizeof(G));
for(i = 0; i < M; i ++)
{
scanf("%d%d%d", &a, &b, &temp);
a --;
b --;
if(!G[a][b] || MAX - temp > G[a][b])
G[a][b] = MAX - temp;
}
}
int searchpath(int u)
{
int v, temp;
visx[u] = 1;
for(v = 0; v < N; v ++)
if(G[u][v] && !visy[v])
{
temp = A[u] + B[v] - G[u][v];
if(temp == 0)
{
visy[v] = 1;
if(yM[v] == -1 || searchpath(yM[v]))
{
yM[v] = u;
return 1;
}
}
else if(temp < slack)
slack = temp;
}
return 0;
}
int EK()
{
int i, j;
for(i = 0; i < N; i ++)
{
A[i] = 0;
for(j = 0; j < N; j ++)
if(G[i][j] && G[i][j] > A[i])
A[i] = G[i][j];
}
memset(B, 0, sizeof(B));
memset(yM, -1, sizeof(yM));
for(i = 0; i < N; i ++)
{
for(;;)
{
slack = INF;
memset(visx, 0, sizeof(visx));
memset(visy, 0, sizeof(visy));
if(searchpath(i))
break;
if(slack == INF)
return 0;
for(j = 0; j < N; j ++)
{
if(visx[j])
A[j] -= slack;
if(visy[j])
B[j] += slack;
}
}
}
return 1;
}
void printresult()
{
int i, res = 0;
for(i = 0; i < N; i ++)
res += MAX - G[yM[i]][i];
printf("%d\n", res);
}
int main()
{
int i, j;
while(scanf("%d%d", &N, &M) != EOF)
{
init();
if(EK())
printresult();
else
printf("-1\n");
}
return 0;
}



posted on 2011-10-04 19:40  Staginner  阅读(326)  评论(0编辑  收藏  举报