题意:一个无向树,n个点,问最少多少个点可以使每个边都与这些点相连。
题解:最大匹配数
1.最大匹配数等于最小顶点覆盖数。画一个图思考一下就知道了。
2.套用匈牙利算法模板。
3.注意无向图最后匹配数需除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 ;
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 = 0 ; i < n ; i ++)
{
memset(vis , 0 , sizeof(vis)) ;
if(find(i))
ans ++ ;
}
return ans ;
}
int main()
{
int i , j , k ;
int u , num , v ;
int ans ;
while(scanf("%d" , &n) != EOF)
{
for(i = 0 ; i < n ; i ++)
edge[i].clear() ;
for(i = 0 ; i < n ; i ++)
{
scanf("%d:(%d)" , &u , &num) ;
for(j = 0 ; j < num ; j ++)
{
scanf("%d" , &v) ;
edge[u].push_back(v) ;
edge[v].push_back(u) ;
}
}
ans = Match() ;
printf("%d\n" , ans / 2) ;//双向图匹配最后除2
}
}