• POJ2942 Knights of the Round Table(点双连通分量 + 二分图染色)


    题目大概说要让n个骑士坐成一圈,这一圈的人数要是奇数且大于2,此外有些骑士之间有仇恨不能坐在一起,问有多少个骑士不能入座。

    双连通图上任意两点间都有两条不重复点的路径,即一个环。那么,把骑士看做点,相互不仇恨的骑士间连边,能坐在一圈骑士的肯定在同一个点双连通分量上。

    不过还有个条件是人数要大于2:

    • 有这么一个结论:如果一个双连通分量存在奇圈(点数为奇数的环),那么这个双连通分量里所有点一定会包含在某一个奇圈内。
    • 大概是因为,双连通分量里面点为奇数个显然都包含在奇圈里;而如果是偶数个,一部分就包含在那个找到的奇圈,而剩下的偶数-奇数=奇数个点一定也形成一个奇圈。
    • 这样只要判断双连通分量是否存在奇圈即可。而存在奇圈是图是否为二分图的充分必要条件,而判断是否为二分图可以用染色法。

    因此这题就是找双连通分量,找到一个双连通分量后,染色判断它是否包含奇圈,如果是双连通分量内所有点都能入座。

    要注意的是一个点能属于多个点双连通分量。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 #define MAXN 1111
      6 #define MAXM 1111111
      7 struct Edge{
      8     int v,flag,next;
      9 }edge[MAXM<<1];
     10 int NE,head[MAXN];
     11 void addEdge(int u,int v){
     12     edge[NE].v=v; edge[NE].flag=0;
     13     edge[NE].next=head[u]; head[u]=NE++;
     14 }
     15 
     16 int n,ans[MAXN];
     17 
     18 int dn,dfn[MAXN],low[MAXN];
     19 int stack[MAXM],top;
     20 int tag[MAXN],color[MAXN];
     21 
     22 bool dfs(int u){
     23     for(int i=head[u]; i!=-1; i=edge[i].next){
     24         int v=edge[i].v;
     25         if(!tag[v]) continue;
     26         if(color[v]==color[u]) return 1;
     27         if(color[v]==-1){
     28             color[v]=!color[u];
     29             return dfs(v);
     30         }
     31     }
     32     return 0;
     33 }
     34 
     35 void tarjan(int u){
     36     dfn[u]=low[u]=++dn;
     37     for(int i=head[u]; i!=-1; i=edge[i].next){
     38         if(edge[i].flag) continue;
     39         edge[i].flag=edge[i^1].flag=1;
     40         stack[++top]=i;
     41 
     42         int v=edge[i].v;
     43 
     44         if(dfn[v]){
     45             low[u]=min(low[u],dfn[v]);
     46             continue;
     47         }
     48 
     49         tarjan(v);
     50         low[u]=min(low[u],low[v]);
     51 
     52         if(low[v]>=dfn[u]){
     53             memset(tag,0,sizeof(tag));
     54             int k;
     55             do{
     56                 k=stack[top--];
     57                 tag[edge[k].v]=1;
     58                 tag[edge[k^1].v]=1;
     59             }while(edge[k^1].v!=u);
     60             memset(color,-1,sizeof(color));
     61             color[u]=0;
     62             if(dfs(u)){
     63                 for(int i=1; i<=n; ++i){
     64                     if(tag[i]) ans[i]=1;
     65                 }
     66             }
     67         }
     68     }
     69 }
     70 
     71 bool ishate[MAXN][MAXN];
     72 int main(){
     73     int m;
     74     while(~scanf("%d%d",&n,&m) && (n||m)){
     75         memset(ishate,0,sizeof(ishate));
     76         int a,b;
     77         while(m--){
     78             scanf("%d%d",&a,&b);
     79             ishate[a][b]=ishate[b][a]=1;
     80         }
     81 
     82         NE=0;
     83         memset(head,-1,sizeof(head));
     84         for(int i=1; i<=n; ++i){
     85             for(int j=i+1; j<=n; ++j){
     86                 if(i==j) continue;
     87                 if(!ishate[i][j]){
     88                     addEdge(i,j);
     89                     addEdge(j,i);
     90                 }
     91             }
     92         }
     93 
     94         memset(ans,0,sizeof(ans));
     95         dn=0; memset(dfn,0,sizeof(dfn));
     96         top=0;
     97         for(int i=1; i<=n; ++i){
     98             if(dfn[i]==0) tarjan(i);
     99         }
    100 
    101         int res=0;
    102         for(int i=1; i<=n; ++i){
    103             if(!ans[i]) ++res;
    104         }
    105         printf("%d
    ",res);
    106     }
    107     return 0;
    108 }
  • 相关阅读:
    Linux 上的数据可视化工具
    LINUX 暂停、继续进程
    77个常用Linux命令和工具
    必学100个常用linux命令大全
    Canny边缘检測算法原理及其VC实现具体解释(一)
    ACM POJ 2192 Zipper
    【实战】静默安装-oracle 11.2.0.3 on centos 5.10
    C++ 观察者模式样例
    access数据库:怎么直接从access里把数据里同样的文字替换成空字符&quot;&quot;
    垂死挣扎还是涅槃重生 -- Delphi XE5 公布会归来感想
  • 原文地址:https://www.cnblogs.com/WABoss/p/5694413.html
Copyright © 2020-2023  润新知