圆桌骑士。有的骑士之间是相互憎恨的,不能连坐,需要安排奇数个骑士围着桌子坐着,大于3个,求哪些骑士不可能安排到座位。

根据给定的关系,如果两个骑士之间没有憎恨关系,那么连边。最终就是求有多少个点无法位于奇圈之内。

首先求所有联通分量,对于每个连通分量二分图染色,看看是否存在一个奇圈,如果有一个,那么这个联通分量里面的所有点都可以在至少一个奇圈之内。(详细的见白书)

下面重点说说如何找联通分量的。

方法是用一个栈来维护下面走过的边,如果当前点是割点,那么把在这个点后面加入的边全部退出来,把这些点拿出来,就构成了一个独立的联通分量。

这个维护是很有意思的,因为是递归操作,有点难以理解。

结合下面的图来说:

这也就是题目的样例,如图,假设我们现在走1->2->4,现在2是关键点,于是就把2->4这条边出来,(2,4)两个点构成一个分量。

同理的有3,5。

但是问题也许会是,我一开是走的是1->2->3->5,那么会不会导致(2,3,5)构成一个分量,不会的!因为在你处理完3后,3->5这条边就已经被拿出来了,最终也只有(1,2,3)。这个递归和栈的混合运用是有一点难以理解,好好想想就清楚了。

还有一个问题,2-4并不能看成是一个双联通分量,但是在这个题目里面不会对答案产生影响,因为2个点也无法构成奇圈(3个点呢?嘿嘿不会有3个点的情况)。想想就知道了,加油!

召唤代码君:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#define maxn 2000100
using namespace std; vector<int> bcc[maxn];
int next[maxn],first[],to[maxn],edge;
int low[],d[],belong[],color[];
int a[][];
int n,m,T=,bccnum,ans,u,v,dfs_clock;
int U[maxn],V[maxn],top;
bool can[]; void _init()
{
T++,ans=dfs_clock=bccnum=top=,edge=-;
for (int i=; i<=n; i++) low[i]=d[i]=belong[i]=first[i]=-,can[i]=false;
} void addedge(int uu,int vv)
{
edge++;
to[edge]=vv,next[edge]=first[uu],first[uu]=edge;
edge++;
to[edge]=uu,next[edge]=first[vv],first[vv]=edge;
} bool find(int cur,int tag)
{
for (int i=first[cur]; i!=-; i=next[i])
{
if (belong[to[i]]!=tag) continue;
if (color[to[i]]==color[cur]) return true;
if (color[to[i]]!=-) continue;
color[to[i]]=-color[cur];
if (find(to[i],tag)) return true;
}
return false;
} void dfs(int cur,int fa)
{
low[cur]=d[cur]=++dfs_clock;
for (int i=first[cur]; i!=-; i=next[i])
{
if ((i^)==fa) continue;
if (d[to[i]]==-)
{
U[++top]=cur,V[top]=to[i];
dfs(to[i],i);
low[cur]=min(low[cur],low[to[i]]);
if (low[to[i]]>=d[cur])
{
bcc[++bccnum].clear();
for (;;top--)
{
if (belong[U[top]]!=bccnum) belong[U[top]]=bccnum,bcc[bccnum].push_back(U[top]);
if (belong[V[top]]!=bccnum) belong[V[top]]=bccnum,bcc[bccnum].push_back(V[top]);
if (U[top]==cur && V[top]==to[i])
{
top--;
break;
}
}
for (unsigned j=; j<bcc[bccnum].size(); j++) color[bcc[bccnum][j]]=-;
color[bcc[bccnum][]]=;
if (find(bcc[bccnum][],bccnum))
for (unsigned j=; j<bcc[bccnum].size(); j++) can[bcc[bccnum][j]]=true;
}
}
else low[cur]=min(low[cur],low[to[i]]);
}
} int main()
{
while (scanf("%d%d",&n,&m) && (n|m))
{
_init();
while (m--)
{
scanf("%d%d",&u,&v);
a[u][v]=a[v][u]=T;
}
for (int i=; i<=n; i++)
for (int j=i+; j<=n; j++)
if (a[i][j]!=T) addedge(i,j);
for (int i=; i<=n; i++)
if (d[i]==-) dfs(i,-);
for (int i=; i<=n; i++) if (!can[i]) ans++;
printf("%d\n",ans);
}
return ;
}

UVAlive3523_Knights of the Round Table的更多相关文章

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

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

  2. POJ 2942 Knights of the Round Table

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

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

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

  4. 【LA3523】 Knights of the Round Table (点双连通分量+染色问题?)

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

  5. 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 ...

  6. UVALive - 3523 - Knights of the Round Table

    Problem  UVALive - 3523 - Knights of the Round Table Time Limit: 4500 mSec Problem Description Input ...

  7. POJ 2942Knights of the Round Table(tarjan求点双+二分图染色)

    Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 13954   Accepted: 4673 Description Bein ...

  8. 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 ...

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

    http://poj.org/problem?id=2942 各种逗.... 翻译白书上有:看了白书和网上的标程,学习了..orz. 双连通分量就是先找出割点,然后用个栈在找出割点前维护子树,最后如果 ...

随机推荐

  1. GNU构建系统和Autotool

    原文:http://os.51cto.com/art/201609/518191.htm 经常使用Linux的开发人员或者运维人员,可能对configure->make->make ins ...

  2. mysql 分页查询时,如何正确的获取总数

    1. 普遍方法: 使用 COUNT(*) ,例如: SELECT COUNT(*) as total FROM studentTask WHERE subjectName = '高中数学'; 缺点: ...

  3. Qt-网易云音乐界面实现-6 迷你个人中心实现

    这个界面除了麻烦耗时,没有啥技术含量.暂时我也就把它称为迷你个人中心,因为后面还有一个个人中心了. 先看下完成品 左侧是我的,右侧是原生 个人感觉还可以吧,哈哈哈.给我自己奖励一个鸡腿. 看下头文件 ...

  4. SQL Server Management Studio 键盘快捷键

    光标移动键盘快捷键 操作 SQL Server 2012 SQL Server 2008 R2 左移光标 向左键 向左键 右移光标 向右键 向右键 上移光标 向上键 向上键 下移光标 向下键 向下键 ...

  5. [Unity Shader] 切线空间的法线贴图

    切线空间的法线贴图,可以这样理解: #纹理坐标是从0到1,它的坐标是x向右,y向下 #顶点坐标是从-1到-1,坐标是x向右,y向上 1 由表面上某点的切线Tangent.副切线Bitangent.法线 ...

  6. spring 在ssh三大框架中充当的角色

    https://blog.csdn.net/yeah_nn/article/details/79992777

  7. java按照字节切割字符串,解决汉字的问题

    编写一个截取字符串的函数,输入为一个字符串,截取开始地址,截取字节数,输出为按字节截取的字符串. 但是要保证汉字不被截半个, 如“我ABC”,0,4,应该截为“我AB”,输入“我ABC汉DEF”,1, ...

  8. Leetcode_3. Find the longest substring without repeating characters

    3. Find the longest substring without repeating characters Given a string, find the length of the lo ...

  9. 为centos虚拟机配置固定ip

    在virtual上安装centos虚拟机以后,发现虚拟机没有ip,无法联网 将虚拟机的网络适配器改为桥接模式,桥接到物理机的无线网卡 为虚拟机配置固定IP(vi /etc/sysconfig/netw ...

  10. centos7安装oracle的一些问题

    在配置监听的时候尝试了很多次都是不能创建,最后将 /data/oracle/product/11.2.0/db_1/network/admin目录下的listener.ora和tnsname.ora两 ...