原题:http://poj.org/problem?id=2594
题意:
有n个点,m条有向边;
问最少用多少条路径可以覆盖所有的点;
路径可以合并,即如果有很多的点在一条单向的路径上,那么就可以用这一条路径覆盖这些点;
另外,一个单独的点也算作一条路径;
思路:
用floyd合并路径;再求最大匹配数;
最小路径覆盖 = 顶点数-最大匹配数;
#include<stdio.h>
#include<string.h>
const int maxn = 550;
int n, m;
int match[maxn];
bool used[maxn], link[maxn][maxn];
void floyd()
{
for(int k = 1;k<=n;k++)
{
for(int i = 1;i<=n;i++)
{
if(!link[i][k]) continue;
for(int j = 1;j<=n;j++)
{
if(link[k][j])
link[i][j] = true;
}
}
}
}
bool find(int x)
{
for(int i = 1;i<=n;i++)
{
if(link[x][i] && !used[i])
{
used[i] = true;
if(match[i] == 0 || find(match[i]))
{
match[i] = x;
return true;
}
}
}
return false;
}
int main()
{
while(scanf("%d%d", &n, &m)!=EOF)
{
if(n == 0 && m == 0)
break;
memset(link, false, sizeof link);
memset(match, 0, sizeof match);
for(int i = 1;i<=m;i++)
{
int u, v;
scanf("%d%d", &u, &v);
link[u][v] = true;
}
floyd();
int sum = 0;
for(int i = 1;i<=n;i++)
{
memset(used, false, sizeof used);
if(find(i))
sum++;
}
printf("%d\n", n-sum);
}
return 0;
}