AtCoder Grand Contest 018 F - Two Trees (构造)

Topic

The texture is too blurry, so give it
a link for a faster link

answer

I feel that there is nothing to analyze in the structure problem, and it can be done just how to structure it.

The general main line of thinking is to think about what kind of situation there is no solution, what kind of structure can prove that there is a solution,

For this question, we will start with how to judge no solution.

First of all, the sum of the weights of each subtree is 1 or -1, then there is an implicit condition, that is, the sum of the weights of each subtree is an odd number, a certain point iiThe weights of all the subtrees of i are odd numbers, and the weights of the subtrees rooted at it are also odd numbers, then the parity of the weights of each point can be judged, which are recorded asf 1 [i]in the two trees.f_1[i]f1[ i ] sumf 2 [i] f_2 [i]f2[ i ] (1 means odd, 0 means even).

Therefore, at least there is only one point f 1 ≠ f 2 f_1\not=f_2f1=f2 It can be judged that there is no solution.

Then, we limit the point weight to − 1, 0, 1 -1,0,11,0,1 One, think about how to structure it.

The final weight of a subtree is 1 or -1, and if the weight of a point with an odd number of points in the word count is an odd number (1 or -1), then except for a certain point, the other 1 and -1 must be Two by two are offset. We connect an edge between the two points that are offset by two (on the third graph). This is how to match and how to match. Usually it is the last remaining in the subtree between the sibling nodes. Matching between points.

The second tree does the same, except that the edges between the two offset points are also connected to the third graph. Since the edges of each tree connected on the third graph are a maximum match , the edges are not adjacent, so there is no odd ring in the third graph as a whole, so it is a bipartite graph, we make it black and white For dyeing, the weight of the black point is 1, the white point is -1, and the point whose weight is not involved is 0, and the construction is successful.

Therefore, we prove that there is a solution through the method of construction if and only if f 1 = f 2 f_1=f_2 at each pointf1=f2, And the point weight of each point can be limited to {− 1, 0, 1} \lbrace-1,0,1\rbrace as long as there is a solution{ 1,0,Within 1 } .

CODE

#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 100005
#define LL long long
#define DB double
#define ENDL putchar('\n')
#define INF 0x7f7f7f7f
LL read() {
    
    
	LL f=1,x=0;char s = getchar();
	while(s < '0' || s > '9') {
    
    if(s=='-')f = -f;s = getchar();}
	while(s >= '0' && s <= '9') {
    
    x=x*10+(s-'0');s = getchar();}
	return f * x;
}
const int MOD = 1000000007;
int n,m,i,j,s,o,k;
int rt1,rt2;
int as[MAXN];
vector<int> g1[MAXN],g2[MAXN],g3[MAXN];
bool f1[MAXN],f2[MAXN],vis[MAXN];
int dfs1(int x) {
    
    
	int las = 0; f1[x] = 0;
	for(int i = 0;i < (int)g1[x].size();i ++) {
    
    
		int y = g1[x][i];
		int po = dfs1(y);
		if(las) {
    
    
			g3[las].push_back(po);
			g3[po].push_back(las);
			las = 0;
		}
		else las = po;
	}
	if(!las) las = x,f1[x] = 1;
	return las;
}
int dfs2(int x) {
    
    
	int las = 0; f2[x] = 0;
	for(int i = 0;i < (int)g2[x].size();i ++) {
    
    
		int y = g2[x][i];
		int po = dfs2(y);
		if(las) {
    
    
			g3[las].push_back(po);
			g3[po].push_back(las);
			las = 0;
		}
		else las = po;
	}
	if(!las) las = x,f2[x] = 1;
	return las;
}
void dfs3(int x,int cl) {
    
    
	vis[x] = 1;
	as[x] = cl;
	for(int i = 0;i < (int)g3[x].size();i ++) {
    
    
		int y = g3[x][i];
		if(!vis[y]) {
    
    
			dfs3(y,-cl);
		}
	}
	return ;
}
int main() {
    
    
	n = read();
	for(int i = 1;i <= n;i ++) {
    
    
		s = read();
		if(s > 0) {
    
    
			g1[s].push_back(i);
		}
		else rt1 = i;
	}
	for(int i = 1;i <= n;i ++) {
    
    
		s = read();
		if(s > 0) {
    
    
			g2[s].push_back(i);
		}
		else rt2 = i;
	}
	dfs1(rt1);
	dfs2(rt2);
	for(int i = 1;i <= n;i ++) {
    
    
		if(f1[i] != f2[i]) {
    
    
			printf("IMPOSSIBLE\n");
			return 0;
		}
		if(f1[i] && !vis[i]) {
    
    
			dfs3(i,1);
		}
	}
	printf("POSSIBLE\n");
	for(int i = 1;i <= n;i ++) {
    
    
		printf("%d ",as[i]);
	}ENDL;
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43960414/article/details/113837991