UVaLive3523 Knights of the Round Table
Description
有 n(n≤1000) 个骑士, m(m≤1000000) 对骑士互相憎恨,要3个以上的骑士且保证互相憎恨的骑士不会坐在相邻位置才能开会议,求多少骑士一定不能参加任何一次会议。
多组测试数据。
Input
每组测试数据:
第一行两个整数,
n
、
接下来
m
行每行两个整数
当
n
,
Output
一个整数,一定不能参加的骑士的个数(原题样例有毒)。
solution
不互相憎恨的骑士间连一条边,能开会的骑士一定在同一个简单奇圈,简单奇圈一定在双连通分量上,只要这个双连通分量不是二分图就信了。
问题就转化成找不在不是二分图的双连通分量上的点的个数。
code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<string.h>
//#include<>
using namespace std;
struct EDGE
{
int v;
EDGE *next;
}edge[2100000],*ind[1100];
struct S
{
int u,v;
}s[2100000];
int n,m,el=0,sl,sum;
bool map[1100][1100],ans[1100];
///
vector<int> bcc[1100];
int pre[1100],Time,bn,bccn[1100];
///
void input(int u,int v)
{
edge[++el].v=v;
edge[el].next=ind[u];
ind[u]=&edge[el];
}
int dfs(int u,int fa)
{
int lowu=pre[u]=++Time,child=0;
for(EDGE *k=ind[u];k!=NULL;k=k->next)
{
int v=k->v;
if(pre[v]==0)
{
s[++sl].v=v,s[sl].u=u;
child++;
int lowv=dfs(v,u);
lowu=min(lowv,lowu);
if(lowv>=pre[u])
{
bcc[++bn].clear();
while(1)
{
int x=s[sl].u,y=s[sl].v;
sl--;
if(bccn[x]!=bn) { bcc[bn].push_back(x); bccn[x]=bn; }
if(bccn[y]!=bn) { bcc[bn].push_back(y); bccn[y]=bn; }
if(x==u&&y==v) break;
}
}
}
else if(pre[v]<pre[u] && v!=fa)
{
s[++sl].v=v,s[sl].u=u;
lowu=min(lowu,pre[v]);
}
}
return lowu;
}
void find_bcc()
{
for(int i=1;i<=n;i++)
{
if(!pre[i]) dfs(i,-1);
}
}
int color[1100];
bool color_che(int u,int c)
{
for(EDGE *k=ind[u];k!=NULL;k=k->next)
{
int v=k->v;
if(bccn[v]!=c) continue;
if(color[v]==color[u]) return 0;
if(!color[v])
{
color[v]=3-color[u];
if(color_che(v,c)==0) return 0;
}
}
return 1;
}
void che()
{
for(int i=1;i<=bn;i++)
{
memset(color,0,sizeof(color));
color[bcc[i][0]]=1;
for(int j=0;j<bcc[i].size();j++) bccn[bcc[i][j]]=i;
if(!color_che(bcc[i][0],i)) for(int j=0;j<bcc[i].size();j++) ans[bcc[i][j]]=1;
}
}
void init()
{
for(int i=0;i<=n;i++){
ind[i]=NULL;
pre[i]=ans[i]=bccn[i]=0;
}
bn=sl=Time=sum=el=0;
}
int main()
{
scanf("%d%d",&n,&m);
init();
while(n!=0&&m!=0)
{
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
map[x][y]=1;
map[y][x]=1;
}
for(int i=1;i<n;i++)
for(int j=i+1;j<=n;j++)
if(!map[i][j]) input(i,j),input(j,i);
else map[i][j]=0;
find_bcc();
che();
for(int i=1;i<=n;i++) if(!ans[i]) sum++;
printf("%d\n",sum);
scanf("%d%d",&n,&m);
init();
}
return 0;
}