题目链接:https://vjudge.net/problem/UVA-1364

题意:有n个人参加会议,互相憎恨的人不能坐在相邻的位置,并且每个会议参加的人数必须是奇数,求有多少个人不能参加任何一个会议。

思路:如果两个人可以坐在一起,则在他们之间建立一条无向边。求不在任何一个简单奇圈上面的点的个数。简单圈上面的点必然属于同一个点双联通分量,因此首先需要找出所有的点双联通分量、因为二分图是没有奇圈的,所以需要求那些不是二分图的点双联通分量。虽然这些点双联通分量一定含有奇圈,那么是否是所有的点都在奇圈上面呢。v属于点双联通分量B,但是不在属于B的奇圈C上面。根据点双联通的性质,v一定可以到达C中的一个结点u1,v也一定可以到达C中的入一个结点u2,在C中u1到u2的两条路的长度一奇一偶,总能构建出一个奇圈。

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<stack>
#include<vector>
using namespace std;
const int MAXN=1e3+,INF=0x3f3f3f3f,MOD=1e9+;
int n,m;
int vis[MAXN][MAXN];
vector<int>G[MAXN];
int dfs_color=; ///dfs时间戳
int pre[MAXN],post[MAXN];
int bcc_cnt=; ///联通分量
int low[MAXN]; ///u及其后代所能连回的最早祖先的pre值
int iscut[MAXN]; ///割点
vector<pair<int,int> >birdge; ///桥
struct edge
{
int u,v;
};
stack<edge>S;
int bccno[MAXN]; ///点所在的双联通分量
vector<int>bcc[MAXN]; ///双联通分量
int dfs(int u,int fa)
{
int lowu=pre[u]=++dfs_color;
int child=;
for(int i=; 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(v,u);
lowu=min(lowu,lowv);
if(lowv>=pre[u])
{
iscut[u]=true;
if(lowv>pre[u]) birdge.push_back(make_pair(u,v));
bcc_cnt++;
bcc[bcc_cnt].clear();
while(!S.empty())
{
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<&&child==) iscut[u]=;
low[u]=lowu;
return low[u];
}
void find_bcc()
{
bcc_cnt=;
dfs_color=;
memset(pre,,sizeof(pre));
memset(iscut,,sizeof(iscut));
memset(bccno,,sizeof(bccno));
for(int i=; i<=n; i++)
if(!pre[i]) dfs(i,-);
}
void init(int n,int m)
{
memset(vis,,sizeof(vis));
for(int i=; i<=n; i++) G[i].clear();
birdge.clear();
while(m--)
{
int u,v;
scanf("%d%d",&u,&v);
vis[u][v]=vis[v][u]=;
}
for(int i=; i<=n; i++)
{
for(int j=; j<i; j++)
{
if(vis[i][j]) continue;
G[i].push_back(j);
G[j].push_back(i);
}
}
}
int color[MAXN];
int odd[MAXN];
bool bipartite(int u,int d)
{
for (int i = ; i < G[u].size(); i++)
{ int v=G[u][i];
if (bccno[v]!=d) continue;
if (color[v]==color[u]) return false;
if (!color[v])
{
color[v]=-color[u];
if (!bipartite(v,d)) return false;
}
}
return true;
}
int solve()
{
memset(odd,,sizeof(odd));
for(int i=; i<=bcc_cnt; i++)
{
for(int j=;j<bcc[i].size();j++) bccno[bcc[i][j]]=i;
memset(color,,sizeof(color));
color[bcc[i][]]=;
if(!bipartite(bcc[i][],i))
{
for (int j=; j<bcc[i].size(); j++)
odd[bcc[i][j]]=;
}
}
int ans=;
for(int i=; i<=n; i++)
if(!odd[i]) ans++;
return ans;
}
int main()
{
while(scanf("%d%d",&n,&m))
{
if(n==&&m==) break;
init(n,m);
find_bcc();
cout<<solve()<<endl;
}
return ;
}

无向图BCC+二部图

UVA-1364.Knights of the Round Table 无向图BCC的更多相关文章

  1. UVA 1364 - Knights of the Round Table (获得双连接组件 + 二部图推理染色)

    尤其是不要谈了些什么,我想A这个问题! FML啊.....! 题意来自 kuangbin: 亚瑟王要在圆桌上召开骑士会议.为了不引发骑士之间的冲突. 而且可以让会议的议题有令人惬意的结果,每次开会前都 ...

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

    #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #includ ...

  3. uva 3523 Knights of the Round Table

    题意:给你n,m n为有多少人,m为有多少组关系,每组关系代表两人相互憎恨,问有多少个骑士不能参加任何一个会议. 白书算法指南 对于每个双联通分量,若不是二分图,就把里面的节点标记 #include ...

  4. UVAlive3523 Knights of the Round Table(bcc)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18122 [思路] 点-双连通分量 求出bcc,判断每个bcc是否为 ...

  5. POJ2942 UVA1364 Knights of the Round Table 圆桌骑士

    POJ2942 洛谷UVA1364(博主没有翻墙uva实在是太慢了) 以骑士为结点建立无向图,两个骑士间存在边表示两个骑士可以相邻(用邻接矩阵存图,初始化全为1,读入一对憎恨关系就删去一条边即可),则 ...

  6. POJ 2942 Knights of the Round Table

    Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 10911   Acce ...

  7. POJ 2942 Knights of the Round Table - from lanshui_Yang

    Description Being a knight is a very attractive career: searching for the Holy Grail, saving damsels ...

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

    Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 12439   Acce ...

  9. poj 2942 Knights of the Round Table 圆桌骑士(双连通分量模板题)

    Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 9169   Accep ...

随机推荐

  1. ADO.Net 数据库增加

    数据库增加数据其实就是把查询语句换成了增加语句,后面执行语句用操作变量点出一个执行方法 cmm.ExecuteNonQuery();//关键语句,执行CommandText,的SQL语句,增删改都用这 ...

  2. JAVA回文

    package huiwen; import java.util.Scanner; public class Huiwen { public static void main(String[] arg ...

  3. 提升系统的QPS和吞吐量

    简单而言通过增加集群来提升qps和吞吐量 实际上要比这个要复杂 首先我们需要知道系统的瓶颈 我们所知道的系统拓扑架构 对于rest接口而言 系统设施依次是: dns nginx tomcat db/s ...

  4. cacti有图无数据解决办法

    Cacti 安装不久,图像界面出来了,但是一直没有数据. Cacti 日志中的错误或警告也都一个个全部解决.有些需要访问文件的权限也都有了. 1.system utilities –>Rebui ...

  5. python 内置函数(一),低阶内置函数功能汇总

    python  内置函数  68个 今日主要内容: 1.内置函数 一.内置函数 1.内置函数 详细细节内容地址(id):https://mubu.com/edit/odv-2Dkb6j

  6. php打印错误报告

    //error handler functionfunction customError($errno, $errstr){ echo "<b>Error:</b> ...

  7. helm 更改为国内源

     helm init --upgrade -i slpcat/tiller:v2.8.2 --stable-repo-url https://kubernetes.oss-cn-hangzhou.al ...

  8. Allowing GPU memory growth

    By default, TensorFlow maps nearly all of the GPU memory of all GPUs (subject to CUDA_VISIBLE_DEVICE ...

  9. c++面向行的输入getline()和get()

    来源:c++ primer plus 在c++里当我们输入一个字符串时习惯用cin,但是cin只能读取一段不含空格的字符串,如果我们需要读取一段包含空格的字符串时,就需要用到getline()或get ...

  10. 贪吃蛇Food Java实现(二)

    1.antition包Food类 package cn.tcc.snake.antition; import java.awt.Graphics;import java.awt.Point;publi ...