Knights of the Round Table

  • 建补图时注意不能向自己连边
  • 割点可能属于多个点双连通分量,因此染色时需要多次清空
  • 求点双连通分量时,注意需要特判“孤立点”,尽管这道题不影响
  • 引理:在一个点双连通分量中,只要存在一个奇环,那就可以把任意一个点包含在一个奇环内
#include <bits/stdc++.h>
using namespace std;
vector<int>a[1005],dcc[1005];
bool b[1005][1005];
int dfn[1005],low[1005],tot,cnt,col[1005],id[1005];
stack<int>s;
bool f[1005];
bool pd;
void tarjan(int n1,int fa)
{
	dfn[n1]=low[n1]=++tot;
	s.push(n1);
	if(fa==0&&a[n1].size()==0)
	{
		cnt++;
		dcc[cnt].push_back(n1);
	}
	for(int i=0;i<a[n1].size();i++)
	{
		if(a[n1][i]==fa)
		{
			continue;
		}
		if(!dfn[a[n1][i]])
		{
			tarjan(a[n1][i],n1);
			low[n1]=min(low[n1],low[a[n1][i]]);
			if(dfn[n1]<=low[a[n1][i]])
			{
				cnt++;
				while(s.top()!=a[n1][i])
				{
					dcc[cnt].push_back(s.top());
					s.pop();
				}
				dcc[cnt].push_back(a[n1][i]);
				s.pop();
				dcc[cnt].push_back(n1);
			}
		}
		else
		{
			low[n1]=min(low[n1],dfn[a[n1][i]]);
		}
	}
}
void dfs(int n1)
{
	if(pd==false)
	{
		return;
	}
	for(int i=0;i<a[n1].size();i++)
	{
		if(id[a[n1][i]]!=id[n1])
		{
			continue;
		}
		if(!col[a[n1][i]])
		{
			col[a[n1][i]]=3-col[n1];
			dfs(a[n1][i]);
		}
		else if(col[a[n1][i]]!=3-col[n1])
		{
			pd=false;
			break;
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
    int n,m;
    cin>>n>>m;
    while(!(n==0&&m==0))
    {
    	for(int i=1;i<=n;i++)
    	{
    		a[i].clear();
    		dcc[i].clear();
    		dfn[i]=id[i]=0;
    		f[i]=false;
    		for(int j=1;j<=n;j++)
    		{
    			b[i][j]=true;
    		}
    	}
    	for(int i=1;i<=m;i++)
    	{
    		int u,v;
    		cin>>u>>v;
    		b[u][v]=b[v][u]=false;
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++)
    		{
    			if(b[i][j]&&i!=j)
    			{
    				a[i].push_back(j);
    			}
    		}
    	}
    	tot=cnt=0;
    	for(int i=1;i<=n;i++)
    	{
    		if(!dfn[i])
    		{
    			tarjan(i,0);
    			while(s.size())
    			{
    				s.pop();
    			}
    		}
    	}
    	for(int i=1;i<=cnt;i++)
    	{
    		pd=true;
    		col[dcc[i][0]]=1;
    		for(int j=0;j<dcc[i].size();j++)
    		{
    			id[dcc[i][j]]=i;
    			col[dcc[i][j]]=0;
    		}
    		dfs(dcc[i][0]);
    		if(pd==false)
    		{
    			for(int j=0;j<dcc[i].size();j++)
	    		{
	    			f[dcc[i][j]]=true;
	    		}
    		}
    	}
    	cout<<n-accumulate(f+1,f+n+1,0)<<"\n";
    	cin>>n>>m;
    }	
	return 0;
}
posted @ 2025-02-02 17:58  D06  阅读(10)  评论(0)    收藏  举报
//雪花飘落效果