POJ 2594 最小路径覆盖 + 传递闭包

题意:给出一些点与点的关系,有向边,无环。问最少需要多少个机器人可以遍历全图。

一开始我直接打敲了最小路径覆盖,然后WA到死,后来看了DISCUSS里面说的传递闭包,然后去学习了下,给组数据就能很好的说明这个问题。

1 -> 2 , 2 -> 3 , 4 -> 2 ,2 -> 5 .

传递闭包其实就是一个floyd,如果1 -> 2 ,2 -> 3 那么1 -> 3,就将1与3 联通。

 

#include <iostream>

#include <cstdio>

#include <algorithm>

#include <string>

#include <cmath>

#include <cstring>

#include <queue>

#include <set>

#include <vector>

#include <stack>

#include <map>

#include <iomanip>

#define PI acos(-1.0)

#define Max 505

#define inf 1<<28

#define LL(x) (x<<1)

#define RR(x) (x<<1|1)

#define Rep(i,s,t) for(int i=(s);i<=(t);++i)

#define ll long long

#define mem(a,b) memset(a,b,sizeof(a))

#define mp(a,b) make_pair(a,b)

using namespace std;

//

int n , m ;

int Map[Max][Max] ;



bool vis[Max] ;

int link[Max] ;



void init()

{

    mem(vis,0) ;

    mem(link,-1) ;

    mem(Map,0) ;

}



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] == 2 )

                    Map[i][j] = 1 ;

            }

        }

    }

}



int dfs(int x )

{

    for (int i = 1 ; i <= n ; i ++)

    {

        if(Map[x][i] && !vis[i])

        {

            vis[i] = 1 ;

            if(link[i] == -1 || dfs(link[i]))

            {

                link[i] = x ;

                return 1;

            }

        }

    }

    return 0 ;

}



int main()

{

    while(scanf("%d%d",&n,&m) ,(n + m ))

    {

        int a , b;

        init() ;

        for (int i = 0 ; i < m ; i ++)

        {

            scanf("%d%d",&a,&b) ;

            Map[a][b] = 1 ;

        }

        floyd() ;

        int ans = 0 ;

        for (int i = 1 ; i <= n ; i ++)

        {

            mem(vis,0) ;

            ans += dfs(i) ;

        }

        printf("%d\n",n - ans) ;//最小覆盖数 = 点数 - 最大匹配  .

    }

    return 0;

}


 

 

你可能感兴趣的:(poj)