利用了二分图不含奇圈,求补图的点双连通分量是否是二分图来确定多少个骑士不能参加会议
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define M 1000004
#define N 1004
struct Edge
{
int from,to,nex;
} edge[M*2];
int maze[N][N];
int head[N],edgenum;
void add(int u, int v)
{
Edge E = {u,v,head[u]};
edge[edgenum] = E ;
head[u]=edgenum++;
}
int DFN[N],dfs_clock,block;
int Belong[N];
bool iscut[N];
// 割顶的bccno无意义
stack<Edge> S;
vector<int>G[N];
int color[N];
bool vis[N];
bool fuck(int u,int b){
for(int i=head[u];i!=-1;i=edge[i].nex){
int v=edge[i].to;
if(Belong[v]!=b) continue;
if(color[u]==color[v]) return false;
if(!color[v]){
color[v]=3-color[u];
if(!fuck(v,b)) return false;
}
}
return true;
}
int Tarjan(int u,int fa)
{
int lowu, child=0;
lowu = DFN[u] = ++dfs_clock;
for(int i=head[u]; i!=-1; i = edge[i].nex)
{
int v = edge[i].to;
Edge e;
e.from=u,e.to=v;
if(!DFN[v])
{
S.push(e);
child++;
int lowv=Tarjan(v,u);
lowu=min(lowu,lowv);
if(lowv>=DFN[u])
{
iscut[u]=1;
block++;
G[block].clear();
while(1)
{
Edge x=S.top();
S.pop();
if(Belong[x.from]!=block)
{
G[block].push_back(x.from);
Belong[x.from]=block;
}
if(Belong[x.to]!=block)
{
G[block].push_back(x.to);
Belong[x.to]=block;
}
if(x.from==u&&x.to==v)break;
}
memset(color,0,sizeof(color));
color[u]=1;
if(!fuck(u,block)){
for(int i=0;i<G[block].size();i++){
vis[G[block][i]]=1;
}
}
}
}
else if(DFN[v]<DFN[u]&&v!=fa)
{
S.push(e);
lowu=min(lowu,DFN[v]);
}
}
if(fa<0&&child==1) iscut[u]=0;
return lowu;
}
void solve(int l, int r)
{
memset(DFN,0,sizeof(DFN));
memset(iscut,0,sizeof(iscut));
memset(Belong,0,sizeof(Belong));
dfs_clock=block=0;
for(int i=l; i<=r; i++) if(!DFN[i])Tarjan(i,-1);
}
void init()
{
memset(head, -1, sizeof head);
memset(maze,0,sizeof(maze));
memset(vis,0,sizeof(vis));
edgenum = 0;
}
int main(){
int n,m;
int a,b;
while(scanf("%d%d",&n,&m)&&(n+m)){
init();
for(int i=1;i<=m;i++){
scanf("%d%d",&a,&b);
maze[a][b]=maze[b][a]=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)continue;
if(maze[i][j]==1) continue;
add(i,j);
}
}
solve(1,n);
int ans=n;
for(int i=1;i<=n;i++){
if(vis[i]==1)
ans--;
}
printf("%d\n",ans);
}
return 0;
}