题意:
给出一个图,伞兵降落到一个点上,然后只能按照一个方向走,问最少降落几个伞兵可以访问完所有的点?
分析:
这是一个最小路径覆盖问题。
最小路径覆盖就是在一个图中用最少的路径可以覆盖所有的点。
在二分图中 最小路径覆盖=点集-最大匹配数
,对于二分图的最小路径覆盖很好求,那么此题很可惜是一个有向图。不过,可以通过将有向图转化为二分图来求解。
通常的做法是将点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;
}
}
时间: 2024-11-03 22:36:39