【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\n",ans);
123     }
124     return 0;
125 }
[LA 3523]

 

2016-10-20 21:38:24

posted @ 2016-10-20 21:34  konjak魔芋  阅读(595)  评论(0编辑  收藏  举报