[二分图-匈牙利]poj1422

题意:
给出一个图,伞兵降落到一个点上,然后只能按照一个方向走,问最少降落几个伞兵可以访问完所有的点?

分析:
这是一个最小路径覆盖问题。
最小路径覆盖就是在一个图中用最少的路径可以覆盖所有的点。
在二分图中 最小路径覆盖=点集-最大匹配数

这里写图片描述

,对于二分图的最小路径覆盖很好求,那么此题很可惜是一个有向图。不过,可以通过将有向图转化为二分图来求解。
通常的做法是将点i,拆分成i,i’,(i,j)变成(i,j’);
那么
左边是原图,右边是转换后的二分图

那么直接通过匈牙利算法来求出最大匹配就可以解决这个问题了。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#define read freopen("q.in","r",stdin)
#define LL __int64
#define maxn 1003
#define inf 10000000
using namespace std;
vector<int> vt[maxn];
int vis[maxn],f[maxn];

int hungry(int x)
{
    int i;
    vis[x]=1;
    for(i=0;i<vt[x].size();i++)
    {
        int t=vt[x][i];
        if(f[t]==-1 || (vis[f[t]]==0 && hungry(f[t])))
        {
            f[t]=x;
            return 1;
        }
    }
    return 0;
}
int main()
{
   // read;
   int t;
   scanf("%d",&t);
   while(t--)
   {
       int n,i,j,k,m,a,b;
       scanf("%d%d",&n,&m);
       for(i=1;i<=n;i++)vt[i].clear();
       for(i=0;i<m;i++)
       {
           scanf("%d%d",&a,&b);
           vt[a].push_back(b);
       }
       int res=0;
       memset(f,-1,sizeof(f));
       for(i=1;i<=n;i++)
       {
           memset(vis,0,sizeof(vis));
           if(hungry(i))res++;
       }
      // cout<<vt[3].size()<<" ## "<<vt[3][0]<<endl;
       cout<<n-res<<endl;

   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值