UVA 1364 - Knights of the Round Table (找双连通分量 + 二分图染色法判断)

都特么别说话,我先A了这道题! 卧槽啊.....!

题意来自 kuangbin:

亚瑟王要在圆桌上召开骑士会议,为了不引发骑士之间的冲突, 并且能够让会议的议题有令人满意的结果,每次开会前都必须对出席会议的骑士有如下要求: 1、  相互憎恨的两个骑士不能坐在直接相邻的2个位置; 2、  出席会议的骑士数必须是奇数,这是为了让投票表决议题时都能有结果。

注意:1、所给出的憎恨关系一定是双向的,不存在单向憎恨关系。 2、由于是圆桌会议,则每个出席的骑士身边必定刚好有2个骑士。 即每个骑士的座位两边都必定各有一个骑士。 3、一个骑士无法开会,就是说至少有3个骑士才可能开会。

首先根据给出的互相憎恨的图中得到补图。 然后就相当于找出不能形成奇圈的点。 利用下面两个定理: (1)如果一个双连通分量内的某些顶点在一个奇圈中(即双连通分量含有奇圈), 那么这个双连通分量的其他顶点也在某个奇圈中; (2)如果一个双连通分量含有奇圈,则他必定不是一个二分图。反过来也成立,这是一个充要条件。

所以本题的做法,就是对补图求点双连通分量。 然后对于求得的点双连通分量,使用染色法判断是不是二分图,不是二分图,这个双连通分量的点是可以 存在的 */

这样,思路如下:

1.找出所有的双连通分量;

2.判断找出的双联通分量似不似一个二分图,如果是二分图,说明它不含有奇圈,不符合题意,反之符合题意,所以在该连通分量中的点都是可以上桌开会的点...

具体思路就是这个样子了~然后照着刘汝佳大白书上的 找双联通分量 的算法,以及 染色法判二分图 的方法,就ok了

没有办法,太水了我只能理解到这里才能做题了尼玛啊 !!T_T.....

没有大神讲,变量的意思想了一上午卧槽好傻逼。。。

接下来会有一篇给一些变量注释的!大白书上的代码!造福弱逼不用谢!

#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
using namespace std;  

const int N = 1005;  

struct Edge {
    int u, v;
    Edge() {}
    Edge(int u, int v) {
        this->u = u;
        this->v = v;
    }
};
            ///bccno[]是用来表示 编号为i的点在哪一个双连通分量中!
            ///bcc_cnt是用来表示 总共有几个双连通分量
int pre[N], bccno[N], dfs_clock, bcc_cnt;
bool iscut[N];  

vector<int> g[N], bcc[N];///用来存下来每一个双连通分量
stack<Edge> S;  

int dfs_bcc(int u, int fa) {
    int lowu = pre[u] = ++dfs_clock;
    int child = 0;
    for (int i = 0; i < g[u].size(); i++) {
        int v = g[u][i];
        Edge e = Edge(u, v);
        if (!pre[v]) {
            S.push(e);
            child++;
            int lowv = dfs_bcc(v, u);
            lowu = min(lowu, lowv);
            if (lowv >= pre[u]) {
                iscut[u] = true;
                bcc_cnt++; bcc[bcc_cnt].clear(); //start from 1
                while(1) {
                    Edge x = S.top(); S.pop();
                    if (bccno[x.u] != bcc_cnt) {bcc[bcc_cnt].push_back(x.u); bccno[x.u] = bcc_cnt;}
                    if (bccno[x.v] != bcc_cnt) {bcc[bcc_cnt].push_back(x.v); bccno[x.v] = bcc_cnt;}
                    if (x.u == u && x.v == v) break;
                }
            }
        } else if (pre[v] < pre[u] && v != fa) {
            S.push(e);
            lowu = min(lowu, pre[v]);
        }
    }
    if (fa < 0 && child == 1) iscut[u] = false;
    return lowu;
}  

void find_bcc(int n) {
    memset(pre, 0, sizeof(pre));
    memset(iscut, 0, sizeof(iscut));
    memset(bccno, 0, sizeof(bccno));
    dfs_clock = bcc_cnt = 0;
    for (int i = 0; i < n; i++)
        if (!pre[i]) dfs_bcc(i, -1);
}  

int odd[N], color[N];  

bool bipartite(int u, int b) {
    for (int i = 0; i < g[u].size(); i++) {
        int v = g[u][i]; if (bccno[v] != b) continue;
        if (color[v] == color[u]) return false;
        if (!color[v]) {
            color[v] = 3 - color[u];
            if (!bipartite(v, b)) return false;
        }
    }
    return true;
}  

int n, m, A[N][N];  

int main() {
    int cas = 0;
    while (~scanf("%d%d", &n, &m) && n) {
        for (int i = 0; i < n; i++) g[i].clear();
        memset(A, 0, sizeof(A));
        for (int i = 0; i < m; i++) {
            int u, v;
            scanf("%d%d", &u, &v); u--; v--;
            A[u][v] = A[v][u] = 1;
        }
        for (int u = 0; u < n; u++) {
            for (int v = u + 1; v < n; v++)
                if (!A[u][v]) {
                    g[u].push_back(v);
                    g[v].push_back(u);
                }
        }
        find_bcc(n);
        memset(odd, 0, sizeof(odd));
        for (int i = 1; i <= bcc_cnt; i++) {
            memset(color, 0, sizeof(color));
            for (int j = 0; j < bcc[i].size(); j++) bccno[bcc[i][j]] = i;
            int u = bcc[i][0];
            color[u] = 1;
            if (!bipartite(u, i)) {
                for (int j = 0; j < bcc[i].size(); j++)
                    odd[bcc[i][j]] = 1;
            }
        }
        int ans = n;
        for (int i = 0; i < n; i++)
            ans -= odd[i];
        printf("%d\n", ans);
    }
    return 0;
}  
时间: 2024-12-21 14:19:45

UVA 1364 - Knights of the Round Table (找双连通分量 + 二分图染色法判断)的相关文章

UVA 1364 - Knights of the Round Table(双连通+二分图判定)

UVA 1364 - Knights of the Round Table 题目链接 题意:有n个圆桌骑士,知道一些骑士互相憎恨,现在要开圆桌会议,每次最少3个人,必须是奇数人数,并且互相憎恨的骑士不能在相邻,问有多少骑士是一次都无法参加的 思路:把每个骑士可以相邻的连边,然后做双连通分量,然后对于每个连通分量,利用二分图染色判定去判断是否是奇圈 代码: #include <cstdio> #include <cstring> #include <vector> #in

POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]

Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 12439   Accepted: 4126 Description Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress, and drinking with the oth

UVALive-3523 Knights of the Round Table (双连通分量+二分图匹配)

题目大意:有n个骑士要在圆桌上开会,但是相互憎恶的两个骑士不能相邻,现在已知骑士们之间的憎恶关系,问有几个骑士一定不能参加会议.参会骑士至少有3个且有奇数个. 题目分析:在可以相邻的骑士之间连一条无向边,构成一张图G.则问题变成了有几个节点不在奇圈(有奇数个节点的圈)内,并且一个点在圈内最多出现一次.如果G不连通,应该对每一个分量分别求解.奇圈上的点一定在同一个双连通分量内,要找出所有的双连通分量.但是能构成二分图的双连通分量中一定没有奇圈,不能构成二分图的双连通分量中一定含有奇圈,并且分量中所

【POJ 2942】Knights of the Round Table(双联通分量+染色判奇环)

[POJ 2942]Knights of the Round Table(双联通分量+染色判奇环) Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 11661   Accepted: 3824 Description Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress, an

【POJ】2942 Knights of the Round Table(双连通分量)

http://poj.org/problem?id=2942 各种逗.... 翻译白书上有:看了白书和网上的标程,学习了..orz. 强连通分量就是先找出割点,然后用个栈在找出割点前维护子树,最后如果这个是割点那么子树就都是强连通分量,然后本题求的是奇圈,那么就进行黑白染色,判断是否为奇圈即可.将不是奇圈的所有强连通分量的点累计起来即可. #include <cstdio> #include <cstring> #include <cmath> #include <

POJ2942 Knights of the Round Table 点双连通分量,逆图,奇圈

题目链接: poj2942 题意: 有n个人,能够开多场圆桌会议 这n个人中,有m对人有仇视的关系,相互仇视的两人坐在相邻的位置 且每场圆桌会议的人数仅仅能为奇书 问有多少人不能參加 解题思路: 首先构图,将全部的仇视关系视为一条边,最后再取已经得到的图的逆图, 这样图上连接的边就代表能够相邻而坐的关系 然后就是找奇圈了,首先就是要找图中的环(点双连通分量) 这个环为奇环的条件:不是二分图||这个环中的部分点属于其它奇环 这个推断能够通过将已找到的环进行dfs黑白染色推断 最后不在奇环内的总和即

POJ 2942 - Knights of the Round Table(双连通图 Tarjan + 二分判定)

POJ 2942 - Knights of the Round Table(双连通图 Tarjan + 二分判定) ACM 题目地址: POJ 2942 - Knights of the Round Table 题意: 有N个骑士,给出某些骑士之间的仇恨关系,骑士们开会时会围坐在一个圆桌旁.一次会议能够顺利举行,要满足两个条件: 任意相互憎恨的两个骑士不能相邻 开会人数为大于2的奇数 若某个骑士任何会议都不能参加,那么就必须将他踢出,给出骑士之间的仇恨关系,问最少需要踢出多少个骑士? 分析: 把

UvaLive3523 Knights of the Round Table(点双联通分量+二分图染色)

UvaLive3523 Knights of the Round Table 参考了Kuangbin巨的题解. /* POJ 2942 Knights of the Round Table 亚瑟王要在圆桌上召开骑士会议,为了不引发骑士之间的冲突, 并且能够让会议的议题有令人满意的结果,每次开会前都必须对出席会议的骑士有如下要求: 1. 相互憎恨的两个骑士不能坐在直接相邻的2个位置: 2. 出席会议的骑士数必须是奇数,这是为了让投票表决议题时都能有结果. 注意:1.所给出的憎恨关系一定是双向的,不

poj 2942 Knights of the Round Table 【双连通缩点+判奇圈】【经典】

题目:poj 2942 Knights of the Round Table 题意:n个骑士经常一起开会,其中有一些两两相互憎恨,他们不能同一桌,开会要表决一些事情,所以必须奇数个人,最少3个,求永远也参加不了会议的人的个数. 分析:这个题目两点 首先,建图求双连通缩点 建图的话,因为相互憎恨的不能再一块,所以要建补图,让能够在一起的所有的连接,这样的话,如果能存在环且环上的点是奇数个的话就可以参加会议,标记求不能参加的即可. 建好图之后用tarjan算法双连通缩点,把在一个环上的点保存起来.