WOJ 困难的图论 题解

模拟赛T2

一开始就想到一个结论:如果环内有某一条边属于两个及以上简单环,那么这些环上的边都在两个及以上环内。
于是想到了一种非常毒瘤的做法:首先随便一颗生成树,然后对于每一条非树边,利用LCA给它所属的树上路径打上一个标记,只要某个边(可以转为点)被打上了两个及以上的标记,这样就说明某几个非树边形成的环都不满足条件。

由于标记可能很多,我们貌似只需要上传LCA最上面的那一个标记即可。

总之,这个方法不是人做的。


于是我们还可以想到其它的方法:点双连通分量。

这个东西确实不太熟,这应该是我第二次打这个东西(上一次是一年前的这个时候,静态仙人掌建圆方树)

死的很惨的是某些点不在任何一个点双里面,所以说判断不再弹栈的条件一定不能是到割点!!!

由于未知原因RE了qwq

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<vector>
using namespace std;
#define orz cout<<"lyakioi!!!!!!!!!!!!!!!!!"<<endl
inline int r(){int s=0,k=1;char c=getchar();while(!isdigit(c)){if(c=='-')k=-1;c=getchar();}while(isdigit(c)){s=s*10+c-'0';c=getchar();}return s*k;}
int n,m,head[2000051],cnt,b[2000051],low[2000051],dfn[2000051],times,bcnt,sum[2000051],sume[2000051],ans[2000051];
struct node
{
	int from,to,next;
}a[2100001];
void add_edge(int from,int to)
{
	a[++cnt].to=to;
	a[cnt].next=head[from];
	a[cnt].from=from;
	head[from]=cnt;
}
stack<int>q;
vector<int>ve[2100001];
void dfs(int u,int fa)
{
	times++;
	low[u]=dfn[u]=times;
	q.push(u);
	for(int i=head[u];i;i=a[i].next)
	{
		int v=a[i].to;
		if(v==fa)continue;
		if(!dfn[v])
		{
			dfs(v,u);
			low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u])
			{
				bcnt++;
				int x=q.top();
				while(x!=v)
				{
					sum[bcnt]++;
					ve[bcnt].push_back(x);
					q.pop();
					x=q.top();
				}
				q.pop();
				ve[bcnt].push_back(v);
				ve[bcnt].push_back(u);
				sum[bcnt]++;
				sum[bcnt]++;
				
			}
		}
		else low[u]=min(low[u],dfn[v]);
	}
}
int main()
{
	cnt++;
	int x,y;
	n=r();m=r();
	for(int i=1;i<=m;i++)
	{
		x=r();y=r();
		add_edge(x,y);
		add_edge(y,x);
	}
	dfs(1,0);
	for(int i=1;i<=bcnt;i++)
	{
		for(int j=0;j<ve[i].size();j++)b[ve[i][j]]=i;
		for(int j=0;j<ve[i].size();j++)
		{
			int u=ve[i][j];
			for(int k=head[u];k;k=a[k].next)
			{
				int v=a[k].to;
				if(b[u]==b[v]&&dfn[u]>dfn[v])
				{ 
					ans[i]^=(k/2);
					sume[i]++;
				}
			}
		}
	}
	int ttt=0;
	for(int i=1;i<=bcnt;i++)
	{
//		cout<<sume[i]<<" "<<sum[i]<<endl;
		if(sum[i]==sume[i])
		ttt^=ans[i];
	}
	cout<<ttt;
}
posted @ 2021-08-20 21:06  lei_yu  阅读(38)  评论(0)    收藏  举报