题意:一群圆桌骑士,坐圆桌开会,相邻俩其实不能互相憎恨,并且骑士数量要为奇数,问一定不可能参加的骑士数量。
吐槽:题意理解很重要啊,一开始理解错了,以为是最少踢多少人可以开会,然后就顺着这思路以为网上代码全是错的。。。。。。。。后来才发现自己理解错了,才恍然大悟。
思路:
整体思路就是找割点,然后将在割点之后存的边拿出来,看是否构成了奇环,如果是,将这些边所连接的点都标记下,最后输出的是没被标记的点的个数。
这题知识点较多,我从看题到学习需要的只是到最后ac也花了很长时间,下面提供点有用的连接。
某妹子博客 这里面讲的很全面,也很详细
二分图染色判断 网上找到的资料,还是蛮好的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<queue>
using namespace std;
struct edge
{
int u,v;
};
stack<edge>st;
int n,m,fst[1010],next[1000010],node[1000010];
int edgenum,dfn[1010],low[1010],num;
int color[1010],ans;
bool l[1010][1010],ok[1010],p[1010][1010],mark[1010];
void init()
{
num=0;
ans=0;
edgenum=0;
memset(l,0,sizeof(l));
memset(p,0,sizeof(p));
memset(ok,0,sizeof(ok));
memset(dfn,0,sizeof(dfn));
memset(fst,-1,sizeof(fst));
int u,v;
for(int i=0; i<m; i++)
{
scanf("%d%d",&u,&v);
l[u][v]=1;
l[v][u]=1;
}
}
void graph()
{
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(i!=j&&!l[i][j])
{
next[++edgenum]=fst[i];
fst[i]=edgenum;
node[edgenum]=j;
}
}
}
}
bool odd(int x)
{
int u,v;
queue<int>q;
q.push(x);
color[x]=1;
while(!q.empty())
{
u=q.front();
q.pop();
for(int i=fst[u]; i!=-1; i=next[i])
{
v=node[i];
if(mark[v])
{
if(color[v]==0)
{
color[v]=-color[u];
q.push(v);
}
else if(color[u]==color[v])return true;
}
}
}
return false;
}
void paint(int u,edge temp)
{
edge ed;
memset(mark,0,sizeof(mark));
memset(color,0,sizeof(color));
do
{
ed=st.top();
st.pop();
mark[ed.u]=mark[ed.v]=1;
}
while((ed.u!=temp.u)||(ed.v!=temp.v));
if(odd(u))
{
for(int i=1; i<=n; i++)
{
if(mark[i])ok[i]=1;
}
}
}
void tarjan(int u)
{
int v;
dfn[u]=low[u]=++num;
for(int i=fst[u]; i!=-1; i=next[i])
{
v=node[i];
if(!p[u][v])
{
edge temp;
temp.u=u;
temp.v=v;
st.push(temp);
p[u][v]=p[v][u]=1;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])paint(u,temp);
}
else low[u]=min(low[u],dfn[v]);
}
}
}
void solve()
{
for(int i=1; i<=n; i++)
{
if(!dfn[i])tarjan(i);
}
for(int i=1; i<=n; i++)
{
if(!ok[i])ans++;
}
printf("%d\n",ans);
}
int main()
{
while(scanf("%d%d",&n,&m)&&n)
{
init();
graph();
solve();
}
return 0;
}