poj 2594 floyd+最小路径覆盖

传送门

题意:派机器人去火星寻宝,给出一个无环的有向图,机器人可以降落在任何一个点上,再沿着路去其他点探索,我们的任务是计算至少派多少机器人就可以访问到所有的点。有的点可以重复去。

思路:先floyd,把某点能到的点都给求出来,然后最小路径覆盖。

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1<<28
using namespace std;
bool d[505][505];
int fst[505],next[300000],node[300000],en;
int l[505],m,n;
bool vis[505];
void add(int u,int v)
{
    next[en]=fst[u];
    fst[u]=en;
    node[en]=v;
    en++;
}
bool go(int u)
{
    for(int i=fst[u];i!=-1;i=next[i])
    {
        int v=node[i];
        if(!vis[v])
        {
            vis[v]=1;
            if(l[v]==-1||go(l[v]))
            {
                l[v]=u;
                return true;
            }
        }
    }
    return false;
}
int main()
{
    int u,v;
    while(scanf("%d%d",&n,&m))
    {
        if(m==0&&n==0)break;
        en=0;
        memset(fst,-1,sizeof(fst));
        memset(d,0,sizeof(d));
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&u,&v);
            d[u][v]=1;
        }
        for(int x=1;x<=n;x++)
        {
            for(int y=1;y<=n;y++)
            {
                for(int z=1;z<=n;z++)
                {
                    if(d[y][x]&&d[x][z])
                    {
                        d[y][z]=1;
                    }
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(d[i][j])
                {
                    add(i,j);
                }
            }
        }
        int ans=0;
        memset(l,-1,sizeof(l));
        for(int i=1;i<=n;i++)
        {
            memset(vis,0,sizeof(vis));
            if(go(i))ans++;
        }
        cout<<n-ans<<endl;
    }
    return 0;
}


展开阅读全文

没有更多推荐了,返回首页