zoukankan      html  css  js  c++  java
  • 「POJ2942」 Knights of the Round Table(二分图 交叉染色+ 点双连通分量)

    题干:

      亚瑟王要在圆桌上召开骑士会议,为了不引发骑士之间的冲突,并且能够让会议的议题有令人满意的结果,每次开会前都必须对出席会议的骑士有如下要求:
      1、相互憎恨的两个骑士不能坐在直接相邻的2个位置;
      2、出席会议的骑士数必须是奇数,这是为了让投票表决议题时都能有结果。
      如果出现有某些骑士无法出席所有会议(例如这个骑士憎恨所有的其他骑士),则亚瑟王为了世界和平会强制把他剔除出骑士团。现在给定准备去开会的骑士数n,再给出m对憎恨对(表示某2个骑士之间使互相憎恨的),问亚瑟王至少要剔除多少个骑士才能顺利召开会议?

    题解:

      这道题在建边方面还有所讲究。若我们就只是将相互憎恨的士兵连边,后续维护方面十分困难。若我们将不相互憎恨的士兵连边,答案其实就是最大的拥有奇数个节点的环,也就是奇环(因为只有不相互憎恨的士兵才可以坐在一起,我们这样建边就是说谁和谁可以坐在一起)。

      又因为这道题主要是点的问题(去掉多少个骑士,也就是节点),不难想到点双连通分量。

      同样是 tarjan 寻找割点(为了找到环),每找到一个割点,就判断一下是否是二分图(奇环一定有奇数个节点,一定不是二分图)。

      如果是二分图,那就标记掉这个环上的所有点,因为它一定不成立

    Code:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<vector>
     4 #define $ 1111
     5 using namespace std;
     6 int m,n,first[$],tot,tar,dfn[$],low[$],sta[$],up,ans,col[$];
     7 bool vis[$][$],judge[$],whe[$];
     8 struct tree{    int to,next;    }a[$*2000];
     9 inline int min(int x,int y){    return x<y?x:y;    }
    10 inline void add(int x,int y){
    11     a[++tot]=(tree){    y,first[x]    };
    12     first[x]=tot;
    13 }
    14 inline void init(){
    15     memset(first,0,sizeof(first));
    16     memset(a,0,sizeof(a));
    17     memset(dfn,0,sizeof(dfn));
    18     memset(low,0,sizeof(low));
    19     memset(vis,0,sizeof(vis));
    20     memset(sta,0,sizeof(sta));
    21     memset(judge,0,sizeof(judge));
    22     ans=tar=tot=up=0;
    23 }
    24 inline bool dfs(int x,int opt){
    25     whe[x]=0;    col[x]=opt; 
    26     for(register int i=first[x];i;i=a[i].next){
    27         int to=a[i].to;
    28         if(col[to]!=-1&&col[to]==opt)    return 0;
    29         if(whe[to]==1&&dfs(to,opt^1)==0) return 0;
    30     }
    31     return 1;
    32 }
    33 inline void tarjan(int x,int tmp=0){
    34     dfn[x]=low[x]=++tar;
    35     sta[++up]=x;
    36     for(register int i=first[x];i;i=a[i].next){
    37         int to=a[i].to;
    38         if(!dfn[to]){
    39             tarjan(to);
    40             low[x]=min(low[x],low[to]);
    41             if(low[to]>=dfn[x]){
    42                 std::vector<int> out;
    43                 memset(col,-1,sizeof(col));
    44                 memset(whe,0,sizeof(whe));
    45                 do{
    46                     tmp=sta[up--];
    47                     whe[tmp]=1;
    48                     out.push_back(tmp);
    49                 }while(tmp!=to);
    50                 whe[x]=1;  out.push_back(x);
    51                 if(dfs(x,0)==0)
    52                     for(register int j=0;j<out.size();++j) judge[out[j]]=1;
    53             }
    54         }
    55         else low[x]=min(low[x],dfn[to]);
    56     }
    57 }
    58 inline void work(){
    59     for(register int i=1,x,y;i<=m;++i)
    60         scanf("%d%d",&x,&y), vis[x][y]=vis[y][x]=1;
    61     for(register int i=1;i<=n;++i)
    62         for(register int j=1;j<=n;++j)
    63             if(i!=j&&!vis[i][j]) add(i,j);
    64     for(register int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
    65     for(register int i=1;i<=n;++i) if(judge[i]) ans++;
    66     printf("%d
    ",n-ans);
    67 }        
    68 signed main(){
    69     while(~scanf("%d%d",&n,&m)){
    70         if(m+n==0)  return 0;
    71         init(); work();
    72     }
    73 }
    View Code

     

    越努力 越幸运
  • 相关阅读:
    Flink中的广播流之BroadcastStream
    啊。。这是为什么。。 花甜的工作笔记
    我那庞大身躯,脆弱心灵的3250 花甜的工作笔记
    好吧,我承认,我不是一个专一的人。。。 花甜的工作笔记
    沾沾自喜 花甜的工作笔记
    我高调的来啦。。。。 花甜的工作笔记
    今天偶听一词云终端 花甜的工作笔记
    我开始出轨了。 花甜的工作笔记
    软件限制策略。。。。。辛苦中。。 花甜的工作笔记
    推荐系统建构精选文章
  • 原文地址:https://www.cnblogs.com/OI-zzyy/p/11183837.html
Copyright © 2011-2022 走看看