poj2594-Treasure Exploration(最小路径覆盖,最大匹配,floyed(优化))

题目来源:http://poj.org/problem?id=2594

题意

有好多机器人去一个DAG(有向无环图)寻宝藏,问,最少放置几个才可以遍历所有点。

思路

这道题挑明了就是类似hdu1051的题目,求得是最小路径覆盖问题,只不过那道题的伞兵不可移动,而这里的机器人可移动,所以能够移动的话,就代表:mp[1][2]=1,mp[2][3]=1,那么mp[1][3]=1。
所以事先会利用floyed的思想去预处理一下。。。交的时候瞅了一眼时间限制,。。哇,,6000ms,那我就放心了。。。嘿嘿

代码

#include
#include
#include
using namespace std;
const int maxn=500+10;
int mp[maxn][maxn],pre[maxn],vis[maxn];
int n,m;

void init()
{
    memset(mp,0,sizeof(mp));
    while(m--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        mp[l][r]=1;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(mp[i][j])  continue;
            for(int k=1;k<=n;k++)
            {
                if(mp[i][k]&&mp[k][j])
                {
                    mp[i][j]=1;
                }
            }
        }
    }
}
int dfs(int i)
{
    for(int j=1; j<=n; j++)
    {
        if(mp[i][j]&&!vis[j])
        {
            vis[j]=1;
            if(pre[j]==-1||dfs(pre[j]))
            {
                pre[j]=i;
                return 1;
            }
        }
    }
    return 0;
}
void solve()
{
    int ret=0;
    memset(pre,-1,sizeof(pre));
    for(int i=1; i<=n; i++)
    {
        memset(vis,0,sizeof(vis));
        ret+=dfs(i);
    }
    printf("%d\n",n-ret);
}
int main()
{
    while(~scanf("%d%d",&n,&m)&&(n||m))
    {
        init();
        solve();
    }
}

你可能感兴趣的:(ACM竞赛,【图论】--二分图匹配,ACM的进程)