• POJ2942 UVA1364 Knights of the Round Table 圆桌骑士


    POJ2942 洛谷UVA1364(博主没有FQuva实在是太慢了)

    以骑士为结点建立无向图,两个骑士间存在边表示两个骑士可以相邻(用邻接矩阵存图,初始化全为1,读入一对憎恨关系就删去一条边即可),则题意变为求图中不在任何奇环(结点数为奇数的环)中的点的数量。

    一个环上的点一定属于一个双连通分量(两两都有两条路径可达)

    那么什么时候双连通分量中没有奇环呢?

    显然,当双连通分量是二分图的时候,图中没有奇环,因为从一个点出发回到该点一定要经过偶数条边。

    非二分图的双连通分量一定含有奇环

    那么,非二分图的双连通分量的每个点是否都在奇环中呢?

    假设v,u1,u2属于同一个双连通分量,且已知u1,u2在奇环上。求证:v也在奇环上

    因为u1,u2在奇环上,所以u1,u2在环上的两条路径一条长度为奇数,一条长度为偶数。故无论u1-v-u2的长度为奇数或偶数都可以以v,u1,u2构造一个奇圈

    所以我们得到非二分图的双连通分量中的每个点都在奇环上

    那么我们的任务就转换为求无向图中是二分图的双连通分量中点的个数

    有了上面的分析,代码实现就很简单了

      1 #include<cstdio>
      2 #include<cctype>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 #define re register int
      7 int graph[1001][1001];//邻接矩阵 
      8 int dfn[1001],dfs_clock,n,m,stack[1001],top,ans,queue[1001],left,right,color[1001];
      9 int bccno[1001],bcc_cnt,tot;//各个点bcc编号、当前bcc编号、bcc结点数目 
     10 bool odd[1001];//每个点是否在奇圈上 
     11 int read()
     12 {
     13     int f=0,x=0;
     14     char c=getchar();
     15     while(!isdigit(c))
     16     {
     17         f=f|c=='-';
     18         c=getchar();
     19     }
     20     while(isdigit(c))
     21     {
     22         x=(x<<1)+(x<<3)+(c^48);
     23         c=getchar();
     24     }
     25     return x;
     26 }
     27 bool bipartite(int x)//二分图判定 
     28 {
     29     memset(color,0,sizeof(color));
     30     left=right=1;
     31     queue[1]=x;
     32     color[x]=1;
     33     while(right>=left)
     34     {
     35         int u=queue[left++];
     36         for(re v=1;v<=n;v++)
     37         {
     38             if(graph[u][v]&&bccno[v]==bcc_cnt)
     39             {
     40                 if(color[v]==color[u])
     41                     return false;
     42                 else if(!color[v])
     43                 {
     44                     queue[++right]=v;
     45                     color[v]=3^color[u];
     46                 }
     47             }
     48         }
     49     }
     50     return true;
     51 }
     52 int tarjan(int u,int fa)//求双连通分量 
     53 {
     54     int lowu=dfn[u]=++dfs_clock;
     55     for(re v=1;v<=n;v++)
     56         if(graph[u][v])
     57         {
     58             if(!dfn[v])
     59             {
     60                 stack[++top]=v;
     61                 int lowv=tarjan(v,u);
     62                 lowu=min(lowu,lowv);
     63                 if(lowv>=dfn[u])
     64                 {
     65                     tot=0;
     66                     bcc_cnt++;
     67                     while(stack[top]!=v)
     68                     {
     69                         tot++;
     70                         bccno[stack[top--]]=bcc_cnt;
     71                     }
     72                     tot+=2;
     73                     bccno[stack[top--]]=bccno[u]=bcc_cnt;//割点不出栈 
     74                     if(!bipartite(u))//不是二分图,则此BCC中的点均在奇圈上 
     75                         for(re i=1;i<=n;i++)
     76                             if(bccno[i]==bcc_cnt)
     77                                 odd[i]=true;
     78                 }
     79             }
     80             else if(v!=fa)
     81                 lowu=min(lowu,dfn[v]);
     82         }
     83     return lowu;
     84 }
     85 void reset()
     86 {
     87     memset(bccno,0,sizeof(bccno));
     88     memset(dfn,0,sizeof(dfn));
     89     memset(odd,0,sizeof(odd)); 
     90     dfs_clock=bcc_cnt=ans=top=0;
     91     for(re i=1;i<=n;i++)
     92         for(re j=1;j<=n;j++)
     93             graph[i][j]=1;
     94     for(re i=1;i<=n;i++)
     95         graph[i][i]=0;
     96 }
     97 int main()
     98 {
     99     while((n=read())&&(m=read()))
    100     {
    101         reset();
    102         while(m--)
    103         {
    104             int u=read(),v=read();
    105             graph[u][v]=graph[v][u]=0;
    106         }
    107         for(re i=1;i<=n;i++)
    108             if(!dfn[i])
    109             {
    110                 stack[++top]=i;
    111                 tarjan(i,i);
    112             }
    113         for(re i=1;i<=n;i++)
    114             if(!odd[i])
    115                 ans++;
    116         printf("%d
    ",ans);
    117     }
    118     return 0;
    119 }
    Knights of the Round Table 圆桌骑士
  • 相关阅读:
    day7_subprocess模块和面向对象,反射
    python学习之day6,常用标准模块
    python学习之day5,装饰器,生成器,迭代器,json,pickle
    python学习笔记2(pycharm、数据类型)
    Python 学习笔记1
    Python 学习之进制与编码
    网络协议
    Python学习之Python简介
    计算机发展历史
    Java接口
  • 原文地址:https://www.cnblogs.com/LiHaozhe/p/9535281.html
Copyright © 2020-2023  润新知