题意:
给出多个点和某些点的连线。询问可以通过最少多少个点,看到所有叶子
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include <vector>
#include<algorithm>
using namespace std;
const int maxn=1505;
int n,m;
int pre[maxn];//保存各点的匹配点
int vis[maxn];
int voc[maxn];
vector<int> vec[maxn];
int find(int u)//判断是否存在增广路,存在返回1
{
int i,v;
for(i=0;i<vec[u].size();i++)
{
v=vec[u][i];
if(vis[v])continue;
vis[v]=1;
if(pre[v]==-1||find(pre[v]))//-1找到未盖点,find是增广路。
{
pre[v]=u;//匹配边和非匹配边交换
voc[v]=u;
voc[u]=v;
return 1;
}
}
return 0;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
int u,v;
memset(pre,-1,sizeof(pre));
for(int i=0;i<n;i++)
vec[i].clear();
for(int i=0;i<n;i++)
{
scanf("%d:(%d)",&u,&m);
for(int j=0;j<m;j++)
{
scanf("%d",&v);
vec[v].push_back(u);
vec[u].push_back(v);
}
}
memset(voc,-1,sizeof(voc));
int ans=0;
for(int i=0;i<n;i++)
{
memset(vis,0,sizeof(vis));
ans+=find(i);
}/*
for(int i=0;i<n;i++)
{
if(i==voc[voc[i]])
printf("%d %d\n",i,voc[i]);
else
printf("%d -1\n",i);
}*/
printf("%d\n",ans/2);
}
return 0;
}
/*
5
3:(3) 1 4 2
1:(1) 0
2:(0)
0:(1) 2
4:(0)
*/