点双联通分量

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/83549901

找割点,然后把栈中割点下的边拿出来塞在vector中,STL大法好。
POJ 2942 Knights of the Round Table

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<queue>
#include<stack>
#include<vector>
#define maxn 1005
using namespace std;

int n,m;
int dis[maxn][maxn],col[maxn];
struct Edge
{
	int u,v,Prev;
	Edge (int u=0,int v=0):u(u),v(v){}
}E[maxn*maxn];
int info[maxn],cnt_e;
inline void Node(int u,int v){ E[++cnt_e].Prev=info[u],info[u]=cnt_e,E[cnt_e].v=v,E[cnt_e].u=u; }
stack<Edge>s;

bool odd[maxn];
int dfn[maxn],low[maxn],tot,bct,vis[maxn];
vector<int>bcc[maxn];
void dfs(int now,int ff)
{
	low[now] = dfn[now] = ++tot;
	for(int i=info[now];i;i=E[i].Prev)
	{
		if(!dfn[E[i].v])
		{
			s.push(E[i]);
			dfs(E[i].v,now);
			low[now]= min(low[now] , low[E[i].v]);
			if(low[E[i].v] >= dfn[now])
			{
				bcc[++bct].clear();
				for(;!s.empty();)
				{
					if(vis[s.top().u]!=bct) vis[s.top().u]=bct,bcc[bct].push_back(s.top().u);
					if(vis[s.top().v]!=bct) vis[s.top().v]=bct,bcc[bct].push_back(s.top().v);
					if(s.top().u == now && s.top().v == E[i].v){s.pop(); break;}
					s.pop();
				}
			}
		}
		else if(dfn[now] > dfn[E[i].v] && E[i].v!=ff)
			s.push(E[i]), low[now] = min(low[now] , dfn[E[i].v]);
	}
}

int tim = 0;
bool check(int now,int cl)
{
	if(vis[now]!=tim) return 1;
	if(col[now] && col[now]!=cl) return 0;
	else if(col[now] && col[now] == cl) return 1;
	else col[now] = cl;
	for(int i=info[now];i;i=E[i].Prev)
		if(!check(E[i].v,3-cl)) return 0;
	return 1;
}

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		if(!n && !m) return 0;
		memset(dis,0,sizeof dis);
		memset(info,0,sizeof info);
		memset(odd,0,sizeof odd);
		memset(vis,0,sizeof vis);
		memset(dfn,0,sizeof dfn);
		for(;!s.empty();s.pop());
		cnt_e=bct=tot=0;
		for(int i=1,u,v;i<=m;i++) scanf("%d%d",&u,&v),dis[u][v] = 1,dis[v][u] = 1;
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				if(i!=j && dis[i][j] == 0) 
					Node(i,j);
		for(int i=1;i<=n;i++)
			if(!dfn[i]) dfs(i,0);
		for(int i=1;i<=bct;i++)
		{
			int siz = bcc[i].size();tim = i;
			for(int j=0;j<siz;j++) vis[bcc[i][j]] = i,col[bcc[i][j]]=0;
			if(!check(bcc[i][0],1))
				for(int j=0;j<siz;j++) odd[bcc[i][j]] = 1;
		}
		
		int ans = 0;
		for(int i=1;i<=n;i++)
			ans += odd[i];
		printf("%d\n",n-ans);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/83549901