图的联通性问题

    ╮(╯▽╰)╭

  题目:

成为一名骑士是一项非常诱人的职业:寻找圣杯,拯救处于困境的少女以及与其他骑士共饮是一件有趣的事情。因此,近年来亚瑟王王国的骑士人数空前增加,这并不奇怪。现在有这么多的骑士,很少有每个圆桌骑士能够同时来卡梅洛特并坐在圆桌旁的。通常只有一小部分骑士,而其余的骑士则忙着在全国各地做英勇事迹。 

在讨论过程中,骑士特别容易喝酒,容易引起过度兴奋。在发生一些不幸的事故之后,亚瑟王要求著名的巫师梅林(Merlin)确保以后骑士之间不会发生战斗。在仔细研究了问题之后,Merlin意识到只有按照以下两个规则就座骑士,才能避免打架:
  • 骑士的座位应确保彼此仇恨的两个骑士不应该是餐桌上的邻居。(Merlin列出了谁讨厌谁的名单。)骑士们坐在圆桌旁,因此每个骑士都有两个邻居。
  • 桌子周围应该有奇数个骑士。这样可以确保如果骑士们无法达成共识,那么他们可以通过投票解决问题。(如果骑士的数量是偶数,那么可能会发生“是”和“否”具有相同的投票数,并且这种说法会持续下去。)
只有满足这两个规则,Merlin才会让骑士坐下,否则他将取消会议。(如果只有一个骑士出现,那么会议也将被取消,因为一个人不能坐在桌子旁。)Merlin意识到,这意味着有些骑士不能参加任何遵守这些规则的座位安排,并且这些骑士将永远无法坐在圆桌会议上(一种情况是,如果一个骑士讨厌其他每个骑士,但还有许多其他可能的原因)。如果骑士不能坐在圆桌会议上,那么他就不能成为圆桌骑士团的成员,必须将其开除。这些骑士必须转移到一个不太负盛名的骑士团,例如方桌骑士,八角桌骑士或香蕉形桌骑士。为了帮助梅林, 

输入项

输入包含几个测试用例块。每种情况都从包含两个整数1≤n≤1000和1≤m≤1000000的行开始。数字n是骑士数。接下来的m行描述哪个骑士讨厌哪个骑士。这m行中的每行包含两个整数k1和k2,这意味着骑士数k1和骑士数k2彼此讨厌(数字k1和k2在1到n之间)。 

输入由n = m = 0的块终止。 

输出量

对于每个测试用例,您必须在单独的一行上输出一个整数:必须驱逐的骑士数。 

样本输入

5 5
1 4
1 5
2 5
3 4
4 5
0 0

样本输出

2
题解 求点的双联通分量,和二分图的判断(二分图一点是个偶图^_^)
注意 二分图的判断时 不能 return 二分图判断(v,k) 应为儿子还没有访问完,
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
using namespace std;
const int M =400010;
#define ri register int
struct setbian{
    int net,to;
}bian[M];
int head[M],cent,arr[1005][1005],low[M],dfn[M],tim,stk[M],top,color[M],f[M],trmp[M],leve;
vector <int> bcc[M];
void add(int a,int b)
{
    bian[++cent].net=head[a],head[a]=cent;
    bian[cent].to=b;
}
void dfs1(int r,int f)
{
    low[r]=dfn[r]=++tim;
    for(ri i=head[r];i;i=bian[i].net)
    {
        int v=bian[i].to;
        if(dfn[v]==0)
        {
           stk[top++]=v;
            dfs1(v,r);
            low[r]=min(low[r],low[v]);
            if(low[v]>=dfn[r])
            {
                leve++;
                bcc[leve].clear();
                while(top>0)
                {
                    int v2=stk[--top];
                     bcc[leve].push_back(v2);
                     if(v==v2) break;
                }
                bcc[leve].push_back(r);
            }
        }
        else if(v!=f) low[r]=min(low[r],dfn[v]);
    }
}
int dfs2(int r,int num)
{
    for(ri i=head[r];i;i=bian[i].net)
    {
          int v=bian[i].to;
           if(f[v]!=num)        continue;
           if(color[v]==color[r]) return 0;
           if(color[v]==0)
          {
               color[v]=3-color[r];
               if(!dfs2(v,num)) return 0; //  return dfs2(v,num) 这个是错的  
          }
    }
    return 1;
}
int n,m;
int main(){
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0) break;
        memset(arr,0,sizeof arr);
        memset(head,0,sizeof head);
        memset(low,0,sizeof low);
        memset(dfn,0,sizeof dfn);
        memset(color,0,sizeof color);
        memset(stk,0,sizeof stk);
        memset(f,0,sizeof f);
        memset(trmp,0,sizeof trmp);
        top=cent=leve=tim=0;
        int a,b;
        for(ri i=1;i<=m;i++)     //
       scanf("%d%d",&a,&b),arr[a][b]=arr[b][a]=1;
        for(ri i=1;i<=n;i++)
        for(ri j=1;j<=n;j++)
        {
            if(i!=j&&arr[i][j]==0)  //
            add(i,j);
        }
        for(ri i=1;i<=n;i++)      //
        {//cout<<"yes"<<endl;
            if(dfn[i]==0) dfs1(i,0);
        }
         for(ri i=1;i<=leve;i++)  //
         {
             memset(color,0,sizeof color);
             for (ri j=0;j<bcc[i].size();j++)
             {
                     int v=bcc[i][j];
                     f[v]=i;
             }
             color[bcc[i][0]]=1;
             if(!dfs2(bcc[i][0],i))   //
             {
                 for(ri j=0;j<bcc[i].size();j++)
                 {
                     trmp[bcc[i][j]]=1;
                 }
             }
         }
         int ans=n;                //
         for(ri i=1;i<=n;i++)
         {
             if(trmp[i]==1) ans--;
         }
         printf("%d\n",ans);
    }
    return 0;
}
View Code
12-31 06:33