zoukankan      html  css  js  c++  java
  • POJ 2942 Knights of the Round Table 补图+tarjan求点双联通分量+二分图染色+debug

    题面还好,就不描述了


    重点说题解:

    由于仇恨关系不好处理,所以可以搞补图存不仇恨关系,

    如果一个桌子上面的人能坐到一起,显然他们满足能构成一个环

    所以跑点双联通分量

    求点双联通分量我用的是向栈中push边的方法

    请注意:只向栈中push树枝边

    这样每次一对父子(u,v)

    如果low[v]<=dfn[u] 显然u是v所在点双联通分量的割点

    所以栈中边(u,v)之前的边都pop,他们连接的点构成点双联通分量

    我们找到一个点双联通分量之后,由于要求奇数个人坐一桌

    所以满足存在奇环,dfs染色即可

    注意割点可能属于很多点双联通分量,所以染完色之后需要给他把颜色去掉

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<vector>
      5 #include<stack>
      6 #define N 1010
      7 using namespace std;
      8 int n,m,head[N],adj[N][N],ans,dfn[N],low[N],ok[N],ecnt,indx,clr[N],inst[N];
      9 int read()
     10 {
     11     int ret=0,neg=1;
     12     char j=getchar();
     13     for (;j<'0' || j>'9';j=getchar())
     14     if (j=='-') neg=-1;
     15     for (;j<='9' && j>='0';j=getchar())
     16     ret=ret*10+j-'0';
     17     return ret*neg;
     18 }
     19 struct edge
     20 {
     21     int u,v,nxt;
     22 }e[N*N];
     23 stack <edge> stk;
     24 stack <int> tmp;
     25 void add(int u,int v)
     26 {
     27     e[++ecnt].u=u;
     28     e[ecnt].v=v;
     29     e[ecnt].nxt=head[u];
     30     head[u]=ecnt;
     31 }
     32 void getG()//还是推荐链式前向星存图= =
     33 {
     34     for (int i=1,u,v;i<=m;i++)
     35     {
     36     u=read(),v=read();
     37     adj[u][v]=1;
     38     adj[v][u]=1;
     39     }
     40     for (int i=1;i<=n;i++)
     41     for (int j=1;j<=n;j++)
     42         if (adj[i][j]==0 && i!=j) add(i,j);
     43 }
     44 int dfs(int u,int nw)//染色
     45 {
     46     int ret=1;
     47     for (int i=head[u];i;i=e[i].nxt)
     48     {
     49     int v=e[i].v;
     50     if (inst[v]==1)
     51     {
     52         if (clr[v]==-1)
     53         {
     54         clr[v]=1-nw;
     55         ret&=dfs(v,1-nw);
     56         }
     57         else
     58         if (clr[v]==nw) ret=0;
     59     }
     60     }
     61     return ret;
     62 }
     63 void init()
     64 {
     65     memset(ok,0,sizeof(ok));
     66     memset(head,0,sizeof(head));
     67     memset(adj,0,sizeof(adj));
     68     memset(inst,0,sizeof(inst));
     69     ecnt=1;
     70     memset(dfn,0,sizeof(dfn));
     71     memset(clr,-1,sizeof(clr));
     72     indx=0;
     73     ans=0;
     74 }
     75 void tar(int u,int fa)
     76 {
     77     dfn[u]=low[u]=++indx;
     78     for (int i=head[u];i;i=e[i].nxt)
     79     {
     80     int v=e[i].v;
     81     if (!dfn[v])
     82     {
     83         stk.push(e[i]);
     84         tar(v,u);
     85         low[u]=min(low[u],low[v]);
     86         if (low[v]>=dfn[u])//题解找双联通分量部分
     87         {
     88         while (1)
     89         {
     90             edge e=stk.top();
     91             stk.pop();
     92             inst[e.u]=1;
     93             inst[e.v]=1;
     94             tmp.push(e.u);
     95             tmp.push(e.v);
     96             if (e.u==u && e.v==v) break;
     97         }
     98         clr[u]=1;
     99         if (dfs(u,1)==0)
    100             while (!tmp.empty())
    101             {
    102             ok[tmp.top()]=1;
    103             inst[tmp.top()]=0;
    104             tmp.pop();
    105             }
    106         else while (!tmp.empty()) inst[tmp.top()]=0,tmp.pop();
    107         clr[u]=-1;
    108         }
    109     }
    110     else if (v!=fa)
    111         low[u]=min(low[u],dfn[v]);
    112     }
    113 }
    114 int main()
    115 {
    116     n=read();
    117     m=read();
    118     while (n || m)
    119     {
    120     init();
    121     getG();
    122     for (int i=1;i<=n;i++)
    123         if (!dfn[i]) tar(i,-1);
    124     for (int i=1;i<=n;i++)
    125         ans+=ok[i];
    126     printf("%d
    ",n-ans);
    127     n=read(),m=read();
    128     }
    129     return 0;
    130 }
  • 相关阅读:
    AtCoder Regular Contest 077
    FWT模板
    hackerrank Alex对战Fedor
    hackerrank 训练军队
    hackerrank Diameter Minimization
    hackerrank Ticket
    java基础 布局管理器
    java基础 super 子类调用父类
    java基础 字符串 “==” 和 “equals” 比较
    java基础 作业(一)
  • 原文地址:https://www.cnblogs.com/mrsheep/p/7852160.html
Copyright © 2011-2022 走看看