题目来源:http://a/showproblem.php?pid=1054
题意
存在一个点集,使得每一边至少有一个端点存在于点集中。最小点覆盖指的元素最少的集合。
思路
依照公式,最小点覆盖=最大匹配。
但是题中我们算的是两两之间的,所以会有重复,所以最后的结果要除以2。。。(最小路径覆盖与最小点覆盖傻傻分不清、。。。),
邻接矩阵超时了。。。使用了邻接表。。。500+ms,使用Hk应该会更快。。。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1500+10;
struct pp
{
int u,v,nexx;
}node[1000000+10];
int pre[maxn],vis[maxn],first[maxn];
int n,tot;
void ADD(int r,int l)
{
node[++tot].u=r;
node[tot].v=l;
node[tot].nexx=first[r];
first[r]=tot;
}
void init()
{
tot=0;
memset(first,-1,sizeof(first));
for(int i=1;i<=n;i++)
{
int l,r,k;
scanf("%d:(%d)",&l,&k);
while(k--)
{
scanf("%d",&r);
ADD(l,r);
ADD(r,l);
}
}
}
int dfs(int i)
{
for(int j=first[i];j!=-1;j=node[j].nexx)
{
int v=node[j].v;
if(!vis[v])
{
vis[v]=1;
if(pre[v]==-1||dfs(pre[v]))
{
pre[v]=i;
return 1;
}
}
}
return 0;
}
void solve()
{
int ret=0;
memset(pre,-1,sizeof(pre));
for(int i=0;i<n;i++)
{
memset(vis,0,sizeof(vis));
ret+=dfs(i);
}
printf("%d\n",ret/2);
}
int main()
{
while(~scanf("%d",&n))
{
init();
solve();
}
}