P6185 [NOI Online #1 enhancement group] sequence

Posted by mrobertson on Wed, 10 Nov 2021 20:01:48 +0100

Given two sequences of length n \ (A \), \ (B \).

There are m available actions \ ((t_i,u_i,v_i) \).

\(t \) represents the type of operation.

When \ (t=1 \), it means that both \ (a {u_i} \) and \ (a {v_i} \) can be \ (+ 1 \);

When \ (t=2 \), it means that one of \ (a {u_i} \) and \ (a {v_i} \) can be \ (+ 1 \) and the other \ (- 1 \);

There is no limit to the order and number of operations. Can you make \ (A \) into \ (B \)

link

sol

Connect the edges of type \ (2 \) first. We'll get some connected blocks.

Since there are paths at any two points in the connected component, for any \ ((u,v) \), we can use the path \ ((u,v) \) to make \ (a_ + 1 \), \ (A_v-1 \).

Therefore, it is easy to get that for a connected component, we can arbitrarily change the value of nodes without changing the point weight sum of the whole connected component.

This part can be taken and checked, and the reduction point can be removed(

Connect the edges of type \ (1 \) after shrinking.

(1) If the graph at this time is a bipartite graph, obviously, we can arbitrarily change the value of nodes on the premise that the increments on both sides of the bipartite graph are the same.

(2) If it is not a bipartite graph, that is, there is an odd ring, it is obvious that we can make this node \ (\ pm \) an even number through the combination of [a node + the path from this node to the odd Ring + this odd ring].
Thus, we can arbitrarily change the value of nodes under the premise that the point weight and increment are even.

Then the writing method is obvious ()

First connect the edges of type \ (2 \), use the union search set to dye the shrinkage points and calculate the point weight after the shrinkage points; then connect the \ (1 \) edges. For each connected component of the new graph, use black-and-white coloring to determine whether it is a bipartite graph, and the dyeing process counts the sum of black-and-white increments \ (wb_i-wa_i \) respectively. If it is a bipartite graph, judge whether the black-and-white increments are equal, and if not, judge (pseudo) black-and-white increments (i.e. total increments) Is the sum of even
I don't know what happens to negative mod (), so when judging incremental parity + a huge even number

No sample in the first compilation run + WA 55pts submitted for the first time is wrong in the same place, which is the place where the edge is built after the collection is dyed. The former is because the edge is not built according to the color but according to the point number, and the latter is because the two-way edge is not built

I didn't hang up because of the problem of multi test initialization. Fortunately

However, although the overall situation was quite smooth, it took nearly one hour to complete the code itself. It was too slow (sad) (although I was still trying to prove it repeatedly while writing, it was clear when I wrote the summary at the end

P6185 [NOI Online #1 enhancement group] sequence Code
#include <algorithm> 
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define MAXN (int)(1e5+233)
#define MAXM (int)(1e5+233)
#define MAXAB (int)(1e9+233)
using namespace std;
int n,m;
int a[MAXN],b[MAXN];
long long wa[MAXN],wb[MAXN];
long long sum1,sum2;
struct qwq
{
	int nex,to;
}e[MAXM<<1];
int h[MAXN],tot=0;
struct edgee
{
	int u,v;
}E[MAXM];
int Ecnt=0;
inline void add(int x,int y)
{
	e[++tot].to=y;
	e[tot].nex=h[x];
	h[x]=tot;
}
int fa[MAXN];
int found(int x)
{
	if (fa[x]==x) return x;
	return fa[x]=found(fa[x]);
}
int col[MAXN],c_count=0;
int typ[MAXN];
inline void INIT() { for (int i=1;i<=n;i++) fa[i]=i,h[i]=0,typ[i]=0,wa[i]=0,wb[i]=0,col[i]=0; tot=0; c_count=0; Ecnt=0; }

bool dfs_bina(int x)
{
	if (typ[x]==1) sum1+=(wb[x]-wa[x]);
	else if (typ[x]==2) sum2+=(wb[x]-wa[x]);
	bool wnw=true;
	for (int i=h[x],y;i;i=e[i].nex)
	{
		y=e[i].to;
		//printf("Edge: %d %d\n",x,y);
		if (!typ[y])
		{
			typ[y]=3-typ[x];//rem INIT typ[x]
			if (!dfs_bina(y)) wnw=false;
		}
		else if (typ[y]==typ[x]) wnw=false;
	}
	return wnw;
}

inline bool sol2(int x)
{
	sum1=sum2=0;
	typ[x]=1;
	bool wnw=dfs_bina(x);
	
//	printf(":::%d %lld %lld\n",wnw,sum1,sum2);
	
	if (wnw)
	{
		if (sum1==sum2) return true;
		else return false;
	}
	else
	{
		if ((sum1+sum2+1000000000)&1) return false;
		else return true;
	}
}

inline void sol()
{
	scanf("%d%d",&n,&m);
	INIT();
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	for (int j=1;j<=n;j++) scanf("%d",&b[j]);
	for (int i=1,t,u,v,fu,fv;i<=m;i++)
	{
		scanf("%d%d%d",&t,&u,&v);
		if (t==1) E[++Ecnt]=(edgee){u,v};
		else
		{
			fu=found(u); fv=found(v);
			if (fu!=fv) fa[fu]=fv;
		}
	}
	for (int i=1;i<=n;i++)
		if (fa[i]==i) col[i]=++c_count;
	for (int i=1;i<=n;i++)
		col[i]=col[found(i)],wa[col[i]]+=a[i],wb[col[i]]+=b[i];
	for (int i=1;i<=Ecnt;i++)
//		if (col[E[i].u]!=col[E[i].v])
			add(col[E[i].u],col[E[i].v]),add(col[E[i].v],col[E[i].u]);
	bool answer=1;
	for (int i=1;i<=c_count;i++)
		if (!typ[i]) answer&=sol2(i);
	if (answer) printf("YES\n");
	else printf("NO\n");
	return;
}
int main()
{
	int T;
	scanf("%d",&T);
	while (T--) sol();
	return 0;
}

Topics: Union Find