UVALive 3523 Knight of Round Table 圆桌骑士 (无向图点双连通分量)

由于互相憎恨的骑士不能相邻,把可以相邻的骑士连上无向边,会议要求是奇数,问题就是求不再任意一个简单奇圈上的结点个数。

tarjan直接套以前写的,结果就错了,要特别注意把边加入栈的时间。。。还不是很理解这个算法

#include<bits/stdc++.h>
using namespace std;
#define bug(x) cout<<#x<<‘=‘<<x<<endl;
const int maxv = 1000+5;
const int maxe = maxv*maxv;//开小

int dfn[maxv],low[maxv],bccno[maxv],dfs_clock,bcc_cnt;
bool iscut[maxv];
vector<int> bcc[maxv];
int head[maxv],fro[maxe],to[maxe],nxt[maxe],ecnt;

int edges[maxe],top;

void addEdge(int u,int v)
{
    fro[ecnt] = u;
    to[ecnt] = v;
    nxt[ecnt] = head[u];
    head[u] = ecnt++;
}

void tarjan(int u,int fa)
{
    dfn[u] = low[u] = ++dfs_clock;
    for(int i = head[u]; ~i; i = nxt[i]){
        int v = to[i];

        if(!dfn[v]){
            edges[++top] = i;
            tarjan(v,i);
            low[u] = min(low[v],low[u]);
            if(low[u] >= dfn[u]){
                iscut[u] = true;
                bcc_cnt++; bcc[bcc_cnt].clear(); //bcc从1开始
                int U,V;
                do{
                    int e = edges[top--];
                    U = fro[e], V = to[e];
                    if(bccno[U] != bcc_cnt) { bcc[bcc_cnt].push_back(U); bccno[U]=bcc_cnt; }
                    if(bccno[V] != bcc_cnt) { bcc[bcc_cnt].push_back(V); bccno[V]=bcc_cnt; }
                }while(U!=u||V!=v);
            }
        }else  if((i^1) != fa && dfn[v] < dfn[u] ){ low[u] = min(low[u],dfn[v]);  edges[++top] = i; }// == 比 ^优先级高!第二个条件少了会WA是什么原因
    }
}

void find_bcc(int n)
{
    top = 0;
    memset(dfn ,0,sizeof(dfn));
    memset(iscut, 0,sizeof(iscut));
    memset(bccno, 0,sizeof(bccno));
    dfs_clock = bcc_cnt = 0;
    for(int i = 0; i <  n; i++) {
        if(!dfn[i]) {
            tarjan(i,-1);
            iscut[i] = ~nxt[head[i]];// !(nxt[head[i]] == -1);//树根特判,如果只有一个子结点false
        }
    }
}

int color[maxv];
bool bipartite(int u, int b)
{
    for(int i = head[u]; ~i; i = nxt[i]){
        int v = to[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;
}

bool hate[maxv][maxv];
bool inOdd[maxv];

int main()
{
    //freopen("in.txt","r",stdin);
    int n,m;
    while(~scanf("%d%d",&n,&m)&&(n||m)){
        memset(hate,0,sizeof(hate));
        while(m--){
            int u,v; scanf("%d%d",&u,&v); u--,v--;
            hate[u][v] = hate[v][u] = true;
        }
        memset(head,-1,sizeof(head)); ecnt = 0;
        for(int i = 0; i < n; i++)
        for(int j = i+1; j < n; j++) if(!hate[i][j]){
            addEdge(i,j); addEdge(j,i);
        }
        find_bcc(n);
       // bug(bcc_cnt);
        memset(inOdd,0,sizeof(inOdd));
        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++) inOdd[bcc[i][j]] = true;
            }
        }
        int ans = n;
        for(int i= 0; i < n; i++) if(inOdd[i]) ans--;
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-11-05 13:41:51

UVALive 3523 Knight of Round Table 圆桌骑士 (无向图点双连通分量)的相关文章

poj2924--F - Knights of the Round Table(圆桌骑士,经典连通分量)

F - Knights of the Round Table Time Limit:7000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Description Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress, and drinking w

poj2942圆桌骑士(点双连通分量+二分图染色法判奇圈)

之前一直不明白点双连通分量能用来干嘛,比如边双连通分量可以问加几条边能变成边双连通,这个题目是这样的,每个圆桌会议至少三个骑士参加,因为需要表决意见,所以骑士数目必须是奇数个,直到那些骑士互相憎恨,也就是不能坐在一起的,把能坐在一起的建边,求无法参加任何会议的骑士的个数,重点是任何会议,这点非常关键,这道题之前一直卡在这里,还有就是有的人属于好几种双连通分量,所以全部标记之后再减掉比较好,至于奇数个怎么处理呢,今天才知道原来二分图的判断可以解决奇圈的问题,因为如果是二分图的话,我们染色,相邻的涂

UVALive - 3523 Knights of the Round Table(无向图的双连通分量)

题目大意:有n个骑士经常举行圆桌会议,每次圆桌会议至少要有3个骑士参加(且每次参加的骑士数量是奇数个),且所有互相憎恨的骑士不能坐在圆桌旁的相邻位置,问有多少个骑士不可能参加任何一个会议 解题思路:以骑士为点建立无向图G.如果两个骑士可以相邻(即他们并不互相憎恨),即可连一条边. 则题目就转化为求不在任何一个简单奇圈上的结点个数 首先,圈就是一个双连通的分量,所以第一件事就是将所有的双连通分量求出来,接着再判定这个双连通分量是不是奇圈 奇圈的判定就是用二分图染色判定,如果某个圈能被二分图染色,那

poj 2942 Knights of the Round Table(无向图的双连通分量+二分图判定)

#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #

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

Description Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress, and drinking with the other knights are fun things to do. Therefore, it is not very surprising that in recent years the kingdom of King

POJ_2942_Knights of the Round Table(点的双连通分量+二分图判定)

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

poj 2942 Knights of the Round Table - Tarjan

Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress, and drinking with the other knights are fun things to do. Therefore, it is not very surprising that in recent years the kingdom of King Arthur has e

【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

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