zoukankan      html  css  js  c++  java
  • UVA1364 Knights of the Round Table Tarjan求点双联通分量+二分图染色

    UVA1364 Knights of the Round Table

    题目链接

    ​ Tarjan求点双联通分量+二分图染色

    ​ 题中给出了不可以出现在同一个会议的骑士,但这样貌似不好写,我们可以将能够在同一会议中的骑士连边。我们可以发现在同一个奇环内的骑士一定可以开会。

    ​ 连完之后会形成若干个连同块,我们可以知道一个结论,只要一个强连通分量有一个奇环,那么这个强连通分量中所有点都在奇环上。如果这个强联通分量上没有奇环,那它就一定是个二分图。(反过来说也对:如果一个图为二分图,那它肯定没有奇环。)

    ​ 所以这道题我们可以用Tarjan求完强连通分量,然后再对每个强联同分量判断一下是否为二分图就好了。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    inline long long read() {
        long long s = 0, f = 1; char ch;
        while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
        for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
        return s * f;
    }
    
    const int N = 1005;
    int n, m, cnt, tag, tot, top, vcc, root;
    int in[N], col[N], dfn[N], low[N], vst[N], sta[N], head[N], vis[N][N];
    vector <int> d[N];
    struct edge { int to, nxt; } e[N * N * 2];
    
    void add(int x, int y) {
        e[++cnt].nxt = head[x]; head[x] = cnt; e[cnt].to = y;
    }
    
    void clear() {
        for(int i = 1;i <= n; i++) d[i].clear();
        cnt = tot = vcc = top = 0;
        memset(head, 0, sizeof(head)); memset(vis, 0, sizeof(vis));
        memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low));
        memset(col, 0, sizeof(col)); memset(vst, 0, sizeof(vst));
        memset(in, 0, sizeof(in));
    }
    
    void Tarjan(int x) {
        dfn[x] = low[x] = ++ tot; sta[++top] = x;
        if(x == root && !head[x]) {
            d[++vcc].push_back(x); return ;
        }
        for(int i = head[x] ; i ; i = e[i].nxt) {
            int y = e[i].to; 
            if(!dfn[y]) {
                Tarjan(y), low[x] = min(low[x], low[y]);
                if(low[y] >= dfn[x]) {
                    ++vcc; int p;
                    do {
                        p = sta[top--]; d[vcc].push_back(p);
                    }while(p != y);
                    d[vcc].push_back(x);
                }
            }
            else low[x] = min(low[x], dfn[y]);
        }
    }
    
    void judge(int x, int color, int now) {
        col[x] = color;
        for(int i = head[x]; i ; i = e[i].nxt) {
            int y = e[i].to;
            if(in[y] != now) continue;
            if(!col[y]) judge(y, 3 - color, now);
            else if(col[y] == color) { tag = 1; return ; }
        }
    }
    
    int main() {
    
        while(1) {
            n = read(); m = read(); if(!n && !m) break;
            clear();
            for(int i = 1, x, y;i <= m; i++) x = read(), y = read(), vis[x][y] = vis[y][x] = 1;
            for(int i = 1;i <= n; i++) 
                for(int j = 1;j <= n; j++) {
                    if(j == i) continue;
                    if(!vis[i][j]) add(i, j);
                }
    
            for(int i = 1;i <= n; i++) if(!dfn[i]) root = i, Tarjan(i);
    
            for(int i = 1;i <= vcc; i++) {
                for(int j = 0;j < (int)d[i].size(); j++) in[d[i][j]] = i, col[d[i][j]] = 0;
                tag = 0; 
                if(d[i].size()) judge(d[i][0], 1, i);
                if(tag) 
                    for(int j = 0;j < (int)d[i].size(); j++) vst[d[i][j]] = 1;
            }
    
            int ans = 0;
            for(int i = 1;i <= n; i++) if(!vst[i]) ans++;
            printf("%d
    ", ans);
        }
    
        return 0;
    }
    
  • 相关阅读:
    stat(),lstat(),fstat() 获取文件/目录的相关信息
    lseek() 定位一个已经打开的文件
    Android 自定义View修炼-仿360手机卫士波浪球进度的实现
    Android 自定义View修炼-仿QQ5.0 的侧滑菜单效果的实现
    小蔡计算器 V4.0新版全新发布上线啦~欢迎大家下载使用哈~
    小蔡电脑助手3.0新版全新发布上线啦~欢迎大家下载使用哦~
    考试必备神器-真题园手机客户端Android版1.1正式上线啦,欢迎大家下载使用!
    Android开发之位置定位详解与实例解析(GPS定位、Google网络定位,BaiduLBS(SDK)定位)
    Android开发之自定义圆角矩形图片ImageView的实现
    Android开发之自定义圆形的ImageView的实现
  • 原文地址:https://www.cnblogs.com/czhui666/p/13703537.html
Copyright © 2011-2022 走看看