ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

bzoj #4238 loj #2881「JOISC 2014 Day3」电压

2021-10-04 15:31:07  阅读:195  来源: 互联网

标签:2881 电阻 loj Day3 int while 100010 奇环 节点


你知道 Just Odd Inventions 公司吗?这个公司的业务是「只不过是奇妙的发明 / Just Odd Inventions」。这里简称为 JOI 公司。
JOI 公司的某个实验室中有着复杂的电路。电路由 \(n\) 个节点和 \(m\) 根细长的电阻组成。节点编号为 \(1\) 到 \(n\) 。
每个节点可设定为两种电平之一:高电平或者低电平。每个电阻连接两个节点,只有一端是高电平,另一端是低电平的电阻才会有电流流过。两端都是高电平或者低电平的电阻不会有电流流过。
试求:有多少个电阻,可以通过调节各节点的电压,使得「没有电流流经该电阻,且其他 \(m-1\) 根电阻中都有电流流过」。
对了,JOI 公司这个奇妙的电路是用在什么样的发明上的呢?这是公司内的最高机密,除了社长以外谁都不知道哦~

\(2\leq n\leq 10^5,1\leq m\leq 2\cdot 10^5\)

没有电流流经该电阻,且其他 \(m-1\) 根电阻中都有电流流过 .

如果这张图没有环 .

那么,图中的任意一条边都是可以的 .

如果这张图有环.

二分图与非二分图的区别本质是有无奇环 .

翻译一下,即为删掉这条边之后图为二分图,加上这条边图不是二分图 .

进一步的,说明,这条边在奇环上,并且,删掉这条边之后就不会存在奇环 .

考虑建出 \(dfs\) 树. \(dfs\) 树的一个特点就是每个非树边都是有子孙节点连向祖先节点的 .

此时,边就可以分为两种了,一种是非树边,一种是树边.

对于非树边,这条边必须要构成一个奇环,并且图中只能有一个奇环 . 否则,删除之后,此图还不是二分图.

对于树边,分析一下,必须是所有的奇环都包含了这条边 . 仅此而已吗?并不是,如果奇环上的一条边断掉了,并且存在一个偶环经过这条边,那么,这个奇环的一部分和这个偶环的一部分就会构成一个奇环 . 所以,当前边还不能在偶环上 .

分析完,奇环和偶环个数的求解可以用树上差分 .

时间复杂度 : \(\mathrm O(n+m)\)

空间复杂度 : \(\mathrm O(n+m)\)

code

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	int res=0;
	while(ch>='0'&&ch<='9'){
		res=(res<<3)+(res<<1)+ch-'0';
		ch=getchar();
	}
	return res;
}
inline void print(int res){
	if(res==0){
		putchar('0');
		return;
	}
	int a[10],len=0;
	while(res>0){
		a[len++]=res%10;
		res/=10;
	}
	for(int i=len-1;i>=0;i--)
		putchar(a[i]+'0');
}
int n,m;
vector<pair<int,int> >e;
bool tree[200010],vis[100010];
vector<pair<int,int> >g[100010],tg[100010];
int fa[100010];
int dep[100010],sum[100010][2];
void dfs(int x){
	vis[x]=true;
	for(int i=0;i<(int)g[x].size();i++){
		int to=g[x][i].first,id=g[x][i].second;
		if(!vis[to]){
			tree[id]=true;
			tg[x].push_back(make_pair(to,id));
			tg[to].push_back(make_pair(x,id));
			dfs(to);
		}
	}
}
int tot=0;
queue<int>q;
void bfs(int r){
	while(!q.empty())q.pop();
	dep[r]=0;
	q.push(r);
	while(!q.empty()){
		int x=q.front();
		q.pop();
		for(int i=0;i<(int)tg[x].size();i++){
			int to=tg[x][i].first;
			if(dep[to]==-1){
				dep[to]=dep[x]+1;
				q.push(to);
			}
		}
	}
	vector<int>vs;
	q.push(r);
	fa[r]=-1;
	while(!q.empty()){
		int x=q.front();
		q.pop();
		vs.push_back(x);
		for(int i=0;i<(int)g[x].size();i++){
			int to=g[x][i].first,id=g[x][i].second;
			if((!tree[id])&&(dep[to]<dep[x])){
				if((dep[x]-dep[to])%2==0){
					tot++;
					sum[x][1]++;
					sum[to][1]--;
				}
				else{
					sum[x][0]++;
					sum[to][0]--;
				}
			}
		}
		for(int i=0;i<(int)tg[x].size();i++){
			int to=tg[x][i].first;
			if(dep[to]==dep[x]+1){
				fa[to]=x;
				q.push(to);
			}
		}
	}
	for(int i=(int)vs.size()-1;i>=0;i--){
		int x=vs[i];
		if(fa[x]!=-1){
			sum[fa[x]][0]+=sum[x][0];
			sum[fa[x]][1]+=sum[x][1];
		}
	}
}
int main(){
	n=read();m=read();
	for(int i=0;i<m;i++){
		int u=read()-1,v=read()-1;
		e.push_back(make_pair(u,v));
		g[u].push_back(make_pair(v,i));
		g[v].push_back(make_pair(u,i));
	}
	memset(dep,-1,sizeof(dep));
	for(int i=0;i<n;i++){
		if(!vis[i]){
			dfs(i);
			bfs(i);
		}
	}
	int ans=0;
	for(int i=0;i<m;i++){
		int u=e[i].first,v=e[i].second;
		if(!tree[i]){
			if(dep[u]>dep[v])swap(u,v);
			if(tot==1&&(dep[u]-dep[v])%2==0)ans++;
		}
		else{
			if(dep[u]<dep[v])swap(u,v);
			if(sum[u][1]==tot&&sum[u][0]==0)ans++;
		}
	}
	print(ans);
	putchar('\n');
	return 0;
}
/*inline? ll or int? size? min max?*/

标签:2881,电阻,loj,Day3,int,while,100010,奇环,节点
来源: https://www.cnblogs.com/suadwm/p/15366486.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有