POJ 2594 Treasure Exploration(允许路径重叠的最小路径覆盖)

http://poj.org/problem?id=2594

  允许路径重叠的最小路径覆盖,将连通的点(有向)都连成边,这个用floyd来处理,再用匈

牙利算法求出最大匹配,最后用公式求出最小路径覆盖。

  公式: 顶点数 – 最大匹配 = 最小路径覆盖。

/*
Memory: 428K Time: 782MS
Language: C++ Result: Accepted
*/

#include<cstring>
#include<cstdio>
#include<cstdlib>
const int MAXD = 505;
int n, m;
bool map[MAXD][MAXD], vis[MAXD];
int yM[MAXD], xM[MAXD];

bool dfs( int u)
{
int v;
for( v = 1; v <= n; v ++)
if( map[u][v] && !vis[v])
{
vis[v] = true;
if( yM[v] == -1 || dfs( yM[v]))
{
yM[v] = u, xM[u] = v;
return true;
}
}
return false;
}

int MaxMatch()
{
int u, ret = 0;
memset( xM, -1, sizeof xM);
memset( yM, -1, sizeof yM);
for( u = 1; u <= n; u ++)
{
if( xM[u] == -1) {
memset( vis, false, sizeof vis);
if( dfs(u)) ret ++;
}
}
return ret;
}

void floyd()
{
for( int k = 1; k <= n; k ++)
for( int i = 1; i <= n; i ++)
for( int j = 1; j <= n; j ++)
if( map[i][k] && map[k][j])
map[i][j] = true;
}

int main()
{
while( scanf( "%d%d", &n, &m) == 2)
{
if( n == m && m == 0) break;
memset( map, false, sizeof map);
for( int i = 1; i <= m; i ++)
{
int x, y;
scanf( "%d%d", &x, &y);
map[x][y] = true;
}
floyd();
int ans = n - MaxMatch();
printf( "%d\n", ans);
}
return 0;
}

 

你可能感兴趣的:(exp)