zoukankan      html  css  js  c++  java
  • 【LA3523】 Knights of the Round Table (点双连通分量+染色问题?)

    Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress, and
    drinking with the other knights are fun things to do. Therefore, it is not very surprising that in recent
    years the kingdom of King Arthur has experienced an unprecedented increase in the number of knights.
    There are so many knights now, that it is very rare that every Knight of the Round Table can come
    at the same time to Camelot and sit around the round table; usually only a small group of the knights
    isthere, while the rest are busy doing heroic deeds around the country.
    Knights can easily get over-excited during discussions–especially after a couple of drinks. After
    some unfortunate accidents, King Arthur asked the famous wizard Merlin to make sure that in the
    future no fights break out between the knights. After studying the problem carefully, Merlin realized
    that the fights can only be prevented if the knights are seated according to the following two rules:
    • The knights should be seated such that two knights who hate each other should not be neighbors
    at the table. (Merlin has a list that says who hates whom.) The knights are sitting around a
    roundtable, thus every knight has exactly two neighbors.
    • An odd number of knights should sit around the table. This ensures that if the knights cannot
    agree on something, then they can settle the issue by voting. (If the number of knights is even,
    then itcan happen that “yes” and “no” have the same number of votes, and the argument goes
    on.)
    Merlin will let the knights sit down only if these two rules are satisfied, otherwise he cancels the
    meeting. (If only one knight shows up, then the meeting is canceled as well, as one person cannot sit
    around a table.) Merlin realized that this means that there can be knights who cannot be part of any
    seating arrangements that respect these rules, and these knights will never be able to sit at the Round
    Table (one such case is if a knight hates every other knight, but there are many other possible reasons).
    If a knight cannot sit at the Round Table, then he cannot be a member of the Knights of the Round
    Table and must be expelled from the order. These knights have to be transferred to a less-prestigious
    order, such as the Knights of the Square Table, the Knights of the Octagonal Table, or the Knights
    of the Banana-Shaped Table. To help Merlin, you have to write a program that will determine the
    number of knights that must be expelled.
    Input
    The input contains several blocks of test cases. Each case begins with a line containing two integers
    1 ≤ n ≤ 1000 and 1 ≤ m ≤ 1000000. The number n is the number of knights. The next m lines describe
    which knight hates which knight. Each of these m lines contains two integers k1 and k2, which means
    that knight number k1 and knight number k2 hate each other (the numbers k1 and k2 are between 1
    and n).
    The input is terminated by a block with n = m = 0.
    Output
    For each test case you have to output a single integer on a separate line: the number of knights that
    have to be expelled.
    Sample Input
    5 5
    1 4
    1 5
    2 5
    3 4
    4 5
    0 0
    Sample Output
    2

    【题意】

      给你n个人和m组关系,每组关系表示两个人相互憎恨,而且相互憎恨的人不能在参加一场会议相邻着坐,而且每次会议参加的人数必须为奇数,问最多有多少人不能同时参加一场会议。 

    【分析】

      为什么我没有做圆桌骑士?为什么我没有做圆桌骑士?为什么我没有做圆桌骑士?

      记得以前明明做过嘛- -啊- -怎么找不到带代码,晕..

      再做一次啊。

      其实如果不是一道经典题,还是很难的(像是我这样子的水平,可能建图都想不到ORZ)

      可以把不相互憎恨的两个人之间连一条边,那么每一次参加会议的人就必须在同一个双连通分量上,这样才能形成过一个环形图,关键是如何判断这个环是不是一个奇环,根据二分图的定义,我们知道如果一个环是二分图,那么这个环必定是偶环。

      还有一个定理:若某个点双连通分量中存在奇环,则该点双联通分量中所有点都在某个奇环内。(这个东东画个图想想就好了,想想点双连通的性质,奇数=偶数+奇数)

         判奇环用厉害的染色法。。

    代码如下:

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      7 #include<vector>
      8 #include<stack>
      9 using namespace std;
     10 #define Maxn 1010
     11 
     12 bool a[Maxn][Maxn];
     13 
     14 struct node
     15 {
     16     int x,y,next;
     17 }t[Maxn];int len;
     18 int first[Maxn];
     19 
     20 int mymin(int x,int y) {return x<y?x:y;}
     21 
     22 void ins(int x,int y)
     23 {
     24     t[++len].x=x;t[len].y=y;
     25     t[len].next=first[x];first[x]=len;
     26 }
     27 
     28 int dfn[Maxn],low[Maxn];
     29 
     30 stack<int > s;
     31 vector<int > v[Maxn];
     32 int vl,cnt;
     33 int col[Maxn];
     34 bool q[Maxn];
     35 
     36 void ffind(int x,int f)
     37 {
     38     dfn[x]=low[x]=++cnt;
     39     s.push(x);
     40     for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
     41     {
     42         int y=t[i].y;
     43         if(!dfn[y])
     44         {
     45             ffind(y,x);
     46             low[x]=mymin(low[x],low[y]);
     47             if(low[y]>=dfn[x])
     48             {
     49                 vl++;
     50                 // memset(v[vl],0,sizeof(v[vl]));
     51                 v[vl].clear();
     52                 while(1)
     53                 {
     54                     int z=s.top();
     55                     v[vl].push_back(z);
     56                     if(z==x) break;
     57                     s.pop();
     58                 }
     59             }
     60         }
     61         else low[x]=mymin(low[x],dfn[y]);
     62     }
     63 }
     64 
     65 bool dfs(int x)
     66 {
     67     for(int i=first[x];i;i=t[i].next) if(col[t[i].y]!=-2)
     68     {
     69         int y=t[i].y;
     70         if(col[y]!=-1&&col[y]==col[x]) return 0;
     71         else if(col[y]==-1)
     72         {
     73             col[y]=1-col[x];
     74             if(!dfs(y)) return 0;
     75         }
     76     }
     77     return 1;
     78 }
     79 
     80 int main()
     81 {
     82     int n,m;
     83     while(1)
     84     {
     85         scanf("%d%d",&n,&m);
     86         if(n==0&&m==0) break;
     87         memset(a,1,sizeof(a));
     88         for(int i=1;i<=m;i++)
     89         {
     90             int x,y;
     91             scanf("%d%d",&x,&y);
     92             a[x][y]=a[y][x]=0;
     93         }
     94         len=0;vl=0;cnt=0;
     95         memset(first,0,sizeof(first));
     96         for(int i=1;i<=n;i++)
     97          for(int j=i+1;j<=n;j++) if(a[i][j])
     98          {
     99              ins(i,j);ins(j,i);
    100          }
    101         memset(dfn,0,sizeof(dfn));
    102         while(!s.empty()) s.pop();
    103         for(int i=1;i<=n;i++) if(!dfn[i])
    104         {
    105             ffind(i,0);
    106         }
    107         for(int i=1;i<=n;i++) col[i]=-2;
    108         memset(q,1,sizeof(q));
    109         for(int i=1;i<=vl;i++)
    110         {
    111             for(int j=0;j<v[i].size();j++) col[v[i][j]]=-1;
    112             col[v[i][0]]=1;
    113             int x=v[i][0];
    114             if(!dfs(x))
    115             {
    116                 for(int j=0;j<v[i].size();j++) q[v[i][j]]=0;
    117             }
    118             for(int j=0;j<v[i].size();j++) col[v[i][j]]=-2;
    119         }
    120         int ans=0;
    121         for(int i=1;i<=n;i++) if(q[i]) ans++;
    122         printf("%d
    ",ans);
    123     }
    124     return 0;
    125 }
    [LA 3523]

    2016-10-20 21:38:24

  • 相关阅读:
    QQ恢复解散后的群聊或删除后的好友的方法
    微软双屏手机Surface Duo曝新料
    利用Travis CI+GitHub实现持续集成和自动部署
    利用echarts展示旅行足迹
    03_K近邻算法
    02_感知机算法
    《面试官之你说我听》:简明的图解Redis RDB持久化、AOF持久化
    【绝对有收获】看看?必须告诉你为什么要使用MQ消息中间件(图解版)
    推荐收藏系列:一文理解JVM虚拟机(内存、垃圾回收、性能优化)解决面试中遇到问题(图解版)
    利用window.performance.timing进行性能分析
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/5982691.html
Copyright © 2011-2022 走看看