题目意思说白了就是找最小点覆盖,用树dp和二分图匹配都可以做。以下是二分图匹配的做法:
- #include<cstdio>
#include<iostream>
using namespace std;
const int M=1530; - struct node
{
int u,v;
int next;
}edge[10*M];
int head[M],num;
int color[M],result[M];
bool vis[M];
int n; - void init()
{
for(int i=0;i<=n+1;i++)
{
head[i]=-1;
color[i]=-1;
result[i]=-1;
}
num=0;
} - void addege(int u,int v)
{
edge[num].u=u;
edge[num].v=v;
edge[num].next=head[u];
head[u]=num++;
} - bool find(int a)
{
int i;
for(i=head[a];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(color[v]==0 && !vis[v])
{
vis[v]=true;
if(result[v]==-1 || find(result[v]))
{
result[v]=a;
return true;
}
}
}
return false;
} - int main()
{
while(scanf("%d",&n)==1)
{
init();
int i,j;
int ans=0;
- for(i=0;i<n;i++)
{
int a,b,m;
scanf("%d:(%d)",&a,&m);
if(color[a]==-1) color[a]=1; //通过标记结点颜色建图
for(j=0;j<m;j++)
{
scanf("%d",&b);
color[b]=color[a]^1;
if(color[a]==1)
{
addege(a,b);
}
else if(color[b]==1)
{
addege(b,a);
}
}
}
- for(i=0;i<n;i++)
if(color[i]==1)
{
memset(vis,0,sizeof(vis));
if(find(i)) ans++;
}
printf("%d/n",ans);
}
return 0;
}