P6185 [NOI Online #1 提高组] 序列(二分图)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P6185 [NOI Online #1 提高组] 序列(二分图)相关的知识,希望对你有一定的参考价值。

P6185 [NOI Online #1 提高组] 序列(二分图)

先利用操作二,使用DSU找到连通块,每个点的权值为序列的差值。

然后利用操作一进行连边。

若图为二分图,则两个部分的差值不会变,因此必须两个部分的值必须相同才能满足。

若图不为二分图,则图的权值和的奇偶性不会变,因此差值为偶数即可消除。

// Problem: P6185 [NOI Online #1 提高组] 序列
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P6185
// Memory Limit: 250 MB
// Time Limit: 2000 ms
// Date: 2022-05-23 16:17:16
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
const int hashmod[4] = 402653189,805306457,1610612741,998244353;
#define mst(a,b) memset(a,b,sizeof a)
#define db double
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define ios ios::sync_with_stdio(false),cin.tie(nullptr) 
void Print(int *a,int n)
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 

template <typename T>		//x=max(x,y)  x=min(x,y)
void cmx(T &x,T y)
	if(x<y) x=y;

template <typename T>
void cmn(T &x,T y)
	if(x>y) x=y;

int a[N],b[N];
int n,m;
int s[N];
PII p[N];
ll c[N];
int find(int x)
	return x==s[x]?x:s[x]=find(s[x]);

vector<int>e[N];
int vis[N];
ll sum[3];
inline bool dfs(int u,int k)
	vis[u] = k,sum[k]+=c[u];
	int ok  = 1;
	for(int v:e[u])
		if(vis[u]==vis[v]) ok = 0;
		else if(!vis[v] && !dfs(v,3-k)) ok = 0;
	
	return ok;

bool solve()
		scanf("%d%d",&n,&m);
		rep(i,1,n) scanf("%d",&a[i]),c[i]=vis[i]= 0,s[i] = i ,e[i].clear();
		rep(i,1,n) scanf("%d",&b[i]);
		//printf("m=%d\\n",m);
		//return false;
		map<PII,bool>mp;
		int id = 0;
		rep(i,1,m)
			int op,x,y;
			scanf("%d%d%d",&op,&x,&y);
			//printf("%d,%d,%d\\n",op,x,y);
			//return false;
			if(op==2) s[find(x)]=find(y);
			else if(!mp[x,y]) mp[x,y]=1,p[++id] = x,y;
			//return false;
		
		
		rep(i,1,n) c[find(i)]+=b[i]-a[i];
		rep(i,1,id)
			int x = p[i].x,y=p[i].y;
			//printf("%d,%d\\n",x,y);
			x=find(x),y=find(y);
			e[x].pb(y),e[y].pb(x);
		
		rep(i,1,n)
			if(i==find(i) && !vis[i])
				sum[1] = sum[2] = 0;
				int ok = dfs(i,1);
				//printf("i=%d ok=%d\\n",i,ok);
				if(ok && sum[1]!=sum[2]) return false;
				if(!ok && ((sum[2]^sum[1]) &1) ) return false;
			
			
	return true;

int main()
	int t;scanf("%d",&t);
	//printf("t=%d\\n",t);
	while(t--)
		puts(solve()?"YES":"NO");
	
	return 0;

开发者涨薪指南 48位大咖的思考法则、工作方式、逻辑体系

以上是关于P6185 [NOI Online #1 提高组] 序列(二分图)的主要内容,如果未能解决你的问题,请参考以下文章

NOI Online 2020 #1

noi online round2(入门组)

[NOI Online 2022]如何正确地排序

noi一等奖能保送吗?我有两次noi的一等奖。

第三次noi online爆零记

第三次noi online爆零记