zoukankan      html  css  js  c++  java
  • KNIGHTS

    ~~~题面~~~

    题解:

      考场上只想到了找点双,,,,然后不知道怎么处理奇环的问题。

      我们考虑对图取补集,这样两点之间连边就代表它们可以相邻, 那么一个点合法当且仅当有至少一个大小至少为3的奇环经过了它。

      观察到只会出现一棵类似树的结构 + t个相对独立的环, 因为环肯定都是独立出来的,所以可以不用管它。

      因此我们先找出所有点双,然后判断这个点双内是否有奇环,用二分图染色来判断。如果有奇环,则说明这个点双内的所有点都可以出现在一个奇环上,反之则都不会出现。

      所以我们只需要寻找一下点双,然后判断是否合法并加上相应贡献即可。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define R register int
      4 #define AC 1100
      5 #define ac 11000000
      6 
      7 int n, m, cnt, timer, ans;
      8 int q[AC], top;
      9 int q1[AC], head, tail;
     10 int belong[AC], low[AC], color[AC], dfn[AC];
     11 bool z[AC][AC], vis[AC];
     12 
     13 inline int read()
     14 {
     15     int x = 0;char c = getchar();
     16     while(c > '9' || c < '0') c = getchar();
     17     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
     18     return x;
     19 }
     20 
     21 void pre()
     22 {
     23     n = read(), m = read();
     24     if(!n && !m) exit(0);
     25     memset(belong, 0, sizeof(belong));
     26     memset(vis, 0, sizeof(vis));
     27     memset(dfn, 0, sizeof(dfn));
     28     timer = cnt = ans = top = 0;
     29     memset(z, 0, sizeof(z));
     30     int a, b;
     31     for(R i = 1; i <= m; i ++)
     32     {
     33         a = read(), b = read();
     34         z[a][b] = z[b][a] = true;
     35     }
     36     for(R i = 1; i <= n; i ++) z[i][i] = true;//不能走自环
     37 }
     38 
     39 inline void upmin(int &a, int b){
     40     if(b < a) a = b;
     41 }
     42 
     43 bool check(int x)//检查x所在点双是否是一个二分图
     44 {
     45     memset(color, 0, sizeof(color));
     46     head = tail = 0;
     47     q1[++tail] = x, color[x] = 1;
     48     while(head < tail)
     49     {
     50         x = q1[++head];
     51         for(R i = 1; i <= n; i ++)
     52         {
     53             if(!z[x][i] && belong[i] == cnt)//如果有边并且在同一个点双中
     54             {
     55                 if(color[x] == color[i]) return false;
     56                 else if(!color[i]) q1[++tail] = i, color[i] = color[x] ^ 3;
     57             }
     58         }    
     59     }
     60     return true;
     61 }
     62 
     63 void tarjan(int x, int fa)//求点双联通分量
     64 {
     65     low[x] = dfn[x] = ++ timer;
     66     for(R i = 1; i <= n; i ++)//枚举边
     67     {
     68         if(!z[x][i])
     69         {
     70             if(!dfn[i])
     71             {
     72                 q[++top] = i;//将这个点加入栈
     73                 tarjan(i, x);
     74                 upmin(low[x], low[i]);
     75                 if(low[i] >= dfn[x])//这个点是割点
     76                 {
     77                     int tot = 2;//先加上割点和当前now的tot
     78                     belong[x] = ++ cnt;//先给这个割点临时打上标记
     79                     while(q[top] != i) ++tot, belong[q[top --]] = cnt;//记录下这个点所属的点双联通分量
     80                     belong[q[top --]] = cnt;
     81                     if(!check(x))//不是二分图,那么这个bcc当中的点都是合法的
     82                     {
     83                         int b = top + tot - 1;//直接把刚取出来的点打上标记
     84                         vis[x] = true;//q[top] 不一定是割点
     85                         for(R i = top + 1; i <= b; i ++) vis[q[i]] = true;                        
     86                     }
     87                 }
     88             }    
     89             else if(i != fa) upmin(low[x], dfn[i]);            
     90         }
     91     }
     92 }
     93 
     94 void work()
     95 {
     96     while(1)
     97     {
     98         pre();
     99         for(R i = 1; i <= n; i ++)
    100             if(!dfn[i]) q[++top] = i, tarjan(i, i);//将当前点加入栈
    101         for(R i = 1; i <= n; i ++) if(!vis[i]) ++ans;
    102         printf("%d
    ", ans);
    103     }
    104 }
    105 
    106 int main()
    107 {
    108 //    freopen("in.in", "r", stdin);
    109     work();
    110 //    fclose(stdin);
    111     return 0;
    112 }
    View Code
  • 相关阅读:
    ASP.NET 取得 Uri 各项属性值
    js获取当前时间显示在页面上
    脚步提示及跳转
    整体刷新和局部刷新frameset窗口
    asp.net 字符串过滤
    .net 获取当前网页的的url
    优酷去广告最新的关于如何屏蔽优酷广告的方法
    bat命令集合
    修复IE
    网易见外工作台(AI),语音转文字,快速制作字幕,中英翻译,在线修改字幕
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9896354.html
Copyright © 2011-2022 走看看