poj 2594 Treasure Exploration 最小路径覆盖

题目链接:http://poj.org/problem?id=2594

建图很重要!!!

大致题意:

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

 

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

 

 

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

View Code
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const int MAX=515;
 6 int map[MAX][MAX];
 7 int visit[MAX];
 8 int use[MAX];
 9 int n,m;
10 int solve(int x)
11 {
12     int j;
13     for(j=1;j<=n;j++)
14     {
15         if(map[x][j]&&!visit[j])
16         {
17             visit[j]=1;
18             if(use[j]==-1||solve(use[j]))
19             {
20                 use[j]=x;
21                 return 1;
22             }
23         }
24     }
25     return 0;
26 }
27 int match()
28 {
29     int i,count=0;
30     for(i=1;i<=n;i++)
31     {
32         memset(visit,0,sizeof(visit));
33         if(solve(i))count++;
34     }
35     return count;
36 }
37 void floyd()//本题的顶点可以被覆盖多次所以要对原图进行传递闭包
38 {
39     int i,j,k;
40     for(k=1;k<=n;k++)
41     for(i=1;i<=n;i++)
42     for(j=1;j<=n;j++)
43     if(map[i][k]&&map[k][j])
44     map[i][j]=1;
45 }
46 int main()
47 {
48     int x,y,i,j;
49     while(scanf("%d%d",&n,&m)&&(n+m))
50     {
51         memset(use,-1,sizeof(use));
52         memset(map,0,sizeof(map));
53 
54         for(j=1;j<=m;j++)
55         {
56             scanf("%d%d",&x,&y);
57              map[x][y]=1;
58         }
59         floyd();
60         x=match();
61         printf("%d\n",n-x);
62     }
63     return 0;
64 }

 

 

posted @ 2012-05-07 16:14  我们一直在努力  阅读(258)  评论(0编辑  收藏  举报