题意描述: 有n个骑士,现在要求骑士坐在圆桌上,相邻的两个位置不能坐有冲突的骑士,并且每个圆桌要求坐奇数个人,现在要求出有不能坐在圆桌上的人数(这里要求能坐的尽量坐)
分析:因为题目给出的是有冲突的两个人,那么我们根据题目给出的图建立一个图,两个可以坐在相邻位置的人连边,那么假设他们形成了一个简单的无向环,则很明显如果这个环上的顶点个数为奇数,那么这个环上的人可以坐在一个圆桌上,若顶点数为偶数的话,那么也很显然这些人都不能坐参加会议!如果他们形成了一个复杂的环(即环中有环),若过最大的环为奇数环,我们就直接可以安排他们按最大环上的做,若果最大环为偶数环,如果我能将其拆成若干个奇数环,那么我们就可以安排他们做奇数环个圆桌,否则他们都不能坐,其实说的那么复杂,其实就是先求出图中的双连通分量(顶点个数>=2),若双连通分量中存在奇环,那么这些人都可以坐上圆桌,否则环中的人都不能坐上圆桌,这里因为割点可能会属于多个双连通子图,那么对于割点我们需得特殊处理!!现在就是判断一个环是否存在奇环,那我通过二分染色的方法就可以解决,若染色后,出现两个相同的顶点出现相同的颜色,那么则存在奇环,否则不存在奇环!!
总结:这个人啊,一旦养成烂习惯就很难改掉,我遇到难点的题目就只是简单的想了一下,根本没有多深入的思考,想不出来就去搜别人的解题报告,这是个破习惯,得改啊,所以我在此我做个决定,下次一定绞尽脑汁去思考,我相信只有多思考才能进步得更快!!(能看懂和自己能够解决之间的差距是很大的)!!
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1050;
int g[N][N],n;
int dfn[N],low[N],st[N],index,top,vis[N];
int flag[N],block[N];
bool Vis[N];
int Min(int a,int b)
{
return a>b?b:a;
}
int bfs(int u)
{
int que[N],head=0,tail=1;
que[0]=u;
flag[u]=1;
while(head!=tail)
{
u=que[head];
head=(head+1)%N;
for(int v=1;v<=n;v++)
if(g[u][v]&&vis[v])
if(flag[v]==-1)
{
flag[v]=(flag[u]+1)%2;
que[tail]=v;
tail=(tail+1)%N;
}
else if(flag[v] == flag[u])
return 0;
}
return 1;
}
void Cutvedex(int u)
{
int i;
dfn[u]=low[u]=index++;
st[++top]=u;
for(int v=1;v<=n;v++)
if(g[u][v])
{
if(dfn[v]==-1)
{
Cutvedex(v);
low[u]=Min(low[u],low[v]);
if(low[v]>=dfn[u])
{
memset(vis,0,sizeof(vis));
block[0]=0;
while(true)
{
vis[st[top]]=1;
block[++block[0]]=st[top];
if(st[top--]==v)break;
}
vis[u]=1;
block[++block[0]]=u;
for( i=1;i<=n;i++)flag[i]=-1;
if(!bfs(u))//表示若为一个奇环
for(i=1;i<=block[0];i++)
Vis[block[i]]=1; //标记能坐在圆桌上的人
}
}
else low[u]=Min(low[u],dfn[v]);
}
}
int main ()
{
int m,i,j,x,y;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0)break;
for(i=1;i<=n;i++) //初始化化原图
for(j=1;j<=n;j++)
if(i!=j)
g[i][j]=1;
for(i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
g[x][y]=0;
g[y][x]=0;
}
memset(dfn,-1,sizeof(dfn));
memset(low,0,sizeof(low));
memset(Vis,0,sizeof(Vis));
top=0;index=1;
for(i=1;i<=n;i++)
if(dfn[i]==-1)
Cutvedex(i);
int res=0;
for(i=1;i<=n;i++)
if(Vis[i])
res++;
printf("%d\n",n-res);
}
return 0;
}