题意:n个点m条边的有向无环图,每个点走一次,问最小沿着图走几次可以遍历每个点。
题解:最小路径覆盖数
1.有向图求最大匹配数,最小路径覆盖数 = n - 最大匹配数。
2.套用匈牙利算法的模板即可。
#include<stdio.h>
#include<string.h>
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<vector>
#define MAXN 1505
#define inf 0x3f3f3f3f
using namespace std ;
int n , m ;
bool vis[MAXN] ;
int used[MAXN] ;
vector <int> edge[MAXN] ;
bool find(int u)
{
int i , j ;
int v ;
for(i = 0 ; i < edge[u].size() ; i ++)
{
v = edge[u][i] ;
if(!vis[v])
{
vis[v] = 1 ;
if(used[v] == -1 || find(used[v]))
//find(used[v])的参数used[v]将点v和点used[v]分为了两部分
{
used[v] = u ;
return 1 ;
}
}
}
return 0 ;
}
int Match()
{
int i , j ;
int ans = 0 ;
memset(used , -1 , sizeof(used)) ;
for(i = 1 ; i <= n ; i ++)
{
memset(vis , 0 , sizeof(vis)) ;
if(find(i))
ans ++ ;
}
return ans ;
}
int main()
{
int i , j , k ;
int u , v ;
int t ;
int ans ;
scanf("%d" , &t) ;
while(t --)
{
scanf("%d%d" , &n , &m) ;
for(i = 1 ; i <= n ; i ++)
edge[i].clear() ;
for(i = 0 ; i < m ; i ++)
{
scanf("%d%d" , &u , &v) ;
edge[u].push_back(v) ;
}
ans = Match() ;
printf("%d\n" , n - ans) ;//有向图匹配最后不除2
}
}