Light OJ 1009 - Back to Underworld

来源:互联网 发布:大数据分析入门书籍 编辑:程序博客网 时间:2024/06/06 19:58

   简单的二分图dfs查找。

题意:给定n对关系u,v,表示u,v属于不同种族,问一个种族最大有多少人。

思路:给定一对关系后,就可以把两个点归类到不同集合A,B中,这样就形成了一个二分图,要求A中与B中最多有多少个点,首先dfs染色,染色完后继续dfs找A,B中分别有多少个点。需要特别注意的就是,要考虑图是否连通,所以就要用并查集来区分开互不连通的点集,对每个连通分量再进行上面所说的两次DFS。具体见代码:

#include<iostream>#include<cstdio>#include<cstring>#include<vector>#define sf scanf#define pf printfusing namespace std;const int N=20005;vector<int> G[N];bool ex[N],vis[N],c[N];int ans1,ans2,fa[N];void unit(){    memset(c,0,sizeof(c));    memset(vis,0,sizeof(vis));    memset(ex,0,sizeof(ex));    for(int i=1;i<N;i++)        fa[i]=i,G[i].clear();}void dfs(int u)//dfs染色{    for(int i=0;i<G[u].size();i++)    {        int v=G[u][i];        if(!vis[v])        {            vis[v]=1;            c[v]=!c[u];            dfs(v);        }    }}void dfs1(int u)//找单个连通分量中的点两种类型的点的个数{    if(c[u]==0) ans1++;    else  ans2++;    for(int i=0;i<G[u].size();i++)    {        int v=G[u][i];        if(vis[v])         vis[v]=0,dfs1(v);    }}int root(int a){    if(a==fa[a]) return a;    else  return fa[a]=root(fa[a]);}int main(){    int i,x,y,n,m,T,ca=0;    sf("%d",&T);    while(T--)    {        sf("%d",&n);        unit();        int _max=-1;        while(n--)        {            sf("%d%d",&x,&y);            G[x].push_back(y);            G[y].push_back(x);            ex[x]=ex[y]=1;            x=root(x),y=root(y);//并查集实现合并            fa[x]=y;            x=max(x,y);            _max=max(_max,x);        }        int ans=0;        for(i=1;i<=_max;i++)         if(ex[i]&&fa[i]==i)         {             ans1=0,ans2=0;             vis[i]=1,dfs(i);//两次dfs             vis[i]=0,dfs1(i);             ans+=max(ans1,ans2);//取最大的加上         }        pf("Case %d: %d\n",++ca,ans);    }    return 0;}


0 0