Treasure Exploration(POJ_2594) -有向图可重复点-最小路径覆盖

152 篇文章 0 订阅
10 篇文章 0 订阅

题意: 机器人,探索火星,有n个点,m条边, 边 u->v   为有向边,询问最少派多少机器人可以探索n个点

思路: 与无向图不同的是:  无向图每个匹配的点只能有一个入度 和一个出度 ,但是 在:

1->3  2->3  3->4  3->5 这种情况下,点3 是可以多次经过的,也就是说 3 可以有多个入度出度。

在这种情况下,我们只需要将 1->3->4    2->3->5 看成两条路径。接下来就是如何把3的影响消除:

通过floyd 求传递闭包 可以表示1->4有边 2->5有边。这样一来我们便可以用匈牙利算法来求解。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include <vector>
#include<algorithm>
using namespace std;

const int maxn=1505;
int n,m;        
int g[maxn][maxn];
int pre[maxn];//保存各点的匹配点
int vis[maxn];
//vector<int> vec[maxn];
int find(int u)//判断是否存在增广路,存在返回1
{
    
    for(int i=1;i<=n;i++)
    {
        if(!g[u][i]||vis[i])continue;
        vis[i]=1;
        if(pre[i]==-1||find(pre[i]))//-1找到未盖点,find是增广路。
        {
            pre[i]=u;//匹配边和非匹配边交换
            return 1;
        }
    }
    return 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(g[i][j]==0)
                    if(g[i][k]==1&&g[k][j]==1)
                        g[i][j]=1;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0)
            break;
        memset(pre,-1,sizeof(pre));
        memset(g,0,sizeof(g));
        int u,v,ans=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            g[u][v]=1;
        }
        floyd();
        for(int i=1;i<=n;i++)
        {
            memset(vis,0,sizeof(vis));
            ans+=find(i);
        }
        printf("%d\n",n-ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值