首页 > 代码库 > hdu1054(二分图匹配)

hdu1054(二分图匹配)

题意很简单,在一颗树上找最小点覆盖。

将树染成黑白两色,构成一张二分图,然后最大匹配==最小点覆盖即可,所以一次匈牙利就可以求出来了

hdu1054

 

#include <iostream>#include <stdio.h>#include <string.h>#include <math.h>#include <algorithm>#include <string>#include <queue>#include <vector>#include <stdlib.h>using namespace std;#define N 1505int n;struct node{    int to,next;}edge[N*2];vector<int>g[N];int pre[N],cnt;int cao[N],a[N],b[N];int cnta,cntb;int mark[N],frt[N];void add_edge(int u,int v){    edge[cnt].to=v;    edge[cnt].next=pre[u];    pre[u]=cnt++;}void Dfs(int s,int fr,int flag){    if(flag==0)    {        cao[s]=cnta;        a[cnta]=s;        cnta++;    }else    {        cao[s]=cntb;        b[cntb]=s;        cntb++;    }    for(int p=pre[s];p!=-1;p=edge[p].next)    {        int v=edge[p].to;        if(v==fr) continue;        Dfs(v,s,flag^1);    }}int dfs(int s){    for(int i=0;i<g[s].size();i++)    {        int v=g[s][i];        if(mark[v]==1) continue;        mark[v]=1;        if(frt[v]==-1||dfs(frt[v]))        {            frt[v]=s;            return 1;        }    }    return 0;}int main(){    while(scanf("%d",&n)!=EOF)    {        cnt=0;        memset(pre,-1,sizeof(pre));        for(int i=0;i<n;i++)        {            int x;            scanf("%d",&x);            int num;            scanf(":(%d)",&num);            for(int j=0;j<num;j++)            {                int y;                scanf("%d",&y);                add_edge(x,y);                add_edge(y,x);            }        }        //然后就是染色了        cnta=0; cntb=0;        Dfs(0,-1,0);        //然后再建一张图        for(int i=0;i<cnta;i++)        {            g[i].clear();            for(int p=pre[a[i]];p!=-1;p=edge[p].next)            {                int v=edge[p].to;                g[i].push_back(cao[v]);            }        }        int ans=0;        memset(frt,-1,sizeof(frt));        for(int i=0;i<cnta;i++)        {            memset(mark,0,sizeof(mark));            ans+=dfs(i);        }        printf("%d\n",ans);    }    return 0;}

 

hdu1054(二分图匹配)