您的位置:首页 > 其它

poj 2594 Treasure Exploration 最小路径覆盖

2012-05-07 16:14 585 查看
题目链接:http://poj.org/problem?id=2594

建图很重要!!!

大致题意:

给出一个由n个顶点m条边组成的有向无环图。求最少可以同时存在多少路径,使得这些路径可以覆盖所有的点(注:每个点可以被多条路径覆盖)。

大致思路:
最小路径覆盖的一点小小变形,由于这里的点可以被重复覆盖,所以除了按照普通求最小路径覆盖的方式建立二分图以外,还要对原图用floyd求一遍传递闭包,并更新二分图。接下来用点数n减去最大匹配得到的就是答案

【最小路径覆盖(原图不一定是二分图,但必须是有向图,拆点构造二分图)】:在图中找一些路径,使之覆盖了图中的所有顶点,且任何一个顶点有且只有一条路径与之关联。最小路径覆盖 = |V| - 最大匹配数

View Code

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAX=515;
int map[MAX][MAX];
int visit[MAX];
int use[MAX];
int n,m;
int solve(int x)
{
int j;
for(j=1;j<=n;j++)
{
if(map[x][j]&&!visit[j])
{
visit[j]=1;
if(use[j]==-1||solve(use[j]))
{
use[j]=x;
return 1;
}
}
}
return 0;
}
int match()
{
int i,count=0;
for(i=1;i<=n;i++)
{
memset(visit,0,sizeof(visit));
if(solve(i))count++;
}
return count;
}
void floyd()//本题的顶点可以被覆盖多次所以要对原图进行传递闭包
{
int i,j,k;
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(map[i][k]&&map[k][j])
map[i][j]=1;
}
int main()
{
int x,y,i,j;
while(scanf("%d%d",&n,&m)&&(n+m))
{
memset(use,-1,sizeof(use));
memset(map,0,sizeof(map));

for(j=1;j<=m;j++)
{
scanf("%d%d",&x,&y);
map[x][y]=1;
}
floyd();
x=match();
printf("%d\n",n-x);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: