bzoj 4238 电压

LINK:电压

一张图 每个点可以为黑点或百点 每一条边的两端都必须为一黑一白。询问又多少条边满足除了这条边不满足条件其余所有边都满足条件。

分析一下这个所谓的条件 每一条边的两端必须为一黑一白 所以存在奇环是不被允许的。除此之外的任何条件都是满足的。

至于求答案 可以分析 如果不存在奇环 那么显然偶环上的边 我们也删不掉 所以数量为不是环上的边均可。

考虑存在奇环 那么必然是所有奇环的并集的边的数量。

对于第一种情况 可以求一下边双。对于第二种情况我不太会。。

好吧想的有点复杂了 其实判断环的奇偶 dfs即可利用dfs树可以发形成环的边都是返祖边我们在边返祖的时候借用两点的深度之差即可判断出是奇环还是偶环。

但是这种判环方法有点怪 怎么说呢 大环的奇偶性可以判断出来小环的奇偶性不一定能够体现出来。但是同时小环的奇偶性也同时是不必要的。

首先 我们把dfs树给求出来 然后 加入返祖边 此时我们可以判断出来由返祖边形成的环的奇偶性。

但是我们无法判断 出两条返祖边形成的环 不过也不可能判断出来因为环的个数过多我们不可能数的过来。

可以证明那些小环不必要 因为对于小环形成的奇环来说 我们定义返祖边为奇环的一部分 而奇环和奇环的交集也恰好为其中的一条返祖边。

总而言之 我们只需要判断大环 小环是不必要的 大环就可以决定每条边的所属 不妨考虑形成了一个大的偶环。

那么现在所有边都删不掉了 接下来偶环的并上一个奇环 那么至少有两个奇环 而我们的返祖边就被认定为指定的交集。

不胡言乱语了 dfs树建出 进行树上差分,判断奇环和偶环的个数分别覆盖了每个点多少次 根据次数判断。

至于返祖边形成的额外的奇环或偶环 对答案没有任何影响。(这一点我证明不了。。

值得注意的是 如果判断出只有一个奇环存在 那么那条返祖边一定为交集 对答案贡献+1 反之 多个奇环存在那么返祖边不可能为交集。

用dfs树来判环 这一点值得学习。

const int MAXN=100010;
int n,m,len=1,sum,ans;
int d[MAXN],c[MAXN],s1[MAXN],s2[MAXN];
int lin[MAXN],ver[MAXN<<2],nex[MAXN<<2],mark[MAXN<<2];
inline void add(int x,int y)
{
	ver[++len]=y;nex[len]=lin[x];lin[x]=len;
	ver[++len]=x;nex[len]=lin[y];lin[y]=len;
}
inline void dfs(int x)
{
	for(int i=lin[x];i;i=nex[i])
	{
		int tn=ver[i];
		if(!d[tn])mark[i]=1,d[tn]=d[x]+1,dfs(tn);
		else
		{
			if(d[tn]&&!mark[i^1]&&d[x]>d[tn])
			{
				if((d[x]-d[tn])&1)++s2[x],--s2[tn];
				else ++s1[x],--s1[tn],++sum;
			}
		}
	}
}
inline void dp(int x)
{
	for(int i=lin[x];i;i=nex[i])
	{
		int tn=ver[i];
		if(mark[i])dp(tn),s1[x]+=s1[tn],s2[x]+=s2[tn];
	}
	if(d[x]!=1&&s1[x]==sum&&!s2[x])++ans;
}
int main()
{
	freopen("1.in","r",stdin);
	n=read();m=read();
	rep(1,m,i)add(read(),read());
	rep(1,n,i)
	{
		if(d[i])continue;
		d[i]=1;dfs(i);
	}
	if(sum==1)++ans;
	rep(1,n,i)if(d[i]==1)dp(i);
	put(ans);
	return 0;
}

怎么说呢 dfs树高深莫测 不对。
我再重述一遍这一道题的 关键点 推论1:随便构造出来一棵dfs树 剩下的返祖边对答案的贡献最多为1.
证明:如果某条返祖边构成的是偶环 那么不对答案进行贡献 考虑构成一个奇环 首先我们提到了只有奇环的并集才有价值。

如果我们发现奇环数量为2 那么显然这两个奇环 分别由两个返祖边及树边构成 显然存在两个奇环了 那么剩下所有的返祖边都失去了对答案贡献的能力。

考虑只出现了一个奇环 那么由一条返祖边构成这个奇环 这条返祖尽管可能被若干个小环围住 但是始终是交集 且对答案贡献为1.证毕。

接下来我们考虑 树边 对于形成的偶环 覆盖树边 形成的奇环覆盖的树边我们分别统计标记 进行树上差分即可。

考虑小环对树边的影响如果是偶环内套奇环或偶环那么如论如何奇环都不会偶环的这些树边带来影响。

考虑奇环里套偶环 显然还是偶环的边不必要 且可以发现 此时除了偶环上的边其余边为一个小奇环和外面大奇环的交集 我们采用标记法正确。

考虑奇环里套奇环 对于小环为偶环 我们标记显然不成立 剩下的都成立因为那些边即为交集 且标记也成立。

综上所有情况 我们只把dfs树拉出来采用标记的做法正确 不需要考虑到所有环的影响。

原文地址:https://www.cnblogs.com/chdy/p/12483337.html