[Ybt gold medal navigation 3-6-1] party

get together

Topic link: ybt gold medal navigation 3-6-1

General idea

There are some couples, and then two people can only go to the party alone.
Then there are some restrictions that restrict certain people from going on a date at the same time.
Ask if there is a possibility that each pair can send someone.

Ideas

For this question, when you see one of the two options, and then see the restrictions, and the conditions are related to two people, you will naturally think of 2-SAT.

Then you first look at how to connect the sides.
If there is a condition, AAA andBBB cannot appear at the same time, thenAAA toBBThe other half of B ,BBB toAAThe other half of A.
(Because once you choose one of these two, you must not choose the other, you must only choose the other half)

Then just shrink Tarjan and judge.

Then talk about the process of 2-SAT.
Then you will have two states for each group. According to the topic, they must happen to happen in one of them.
Then if even side aaa tobbb , that is, ifaais introduceda , then you can launchbbb .
Then this is transitive.

Then you can think that if a strong connected component is formed, then if one of them is introduced, then all of them can be introduced.
If there are two points of a certain pair in a strongly connected component, it means a contradiction.
(Because it has strong connected components, it means that either all can be pushed out or neither can be pushed out, but it is contradictory if a pair requires only one outgoing.)

We can use this method to see if it is feasible.

Code

#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

struct node {
    
    
	int to, nxt;
}e[2000001];
int n, m, le[5001], KK;
int	a1, a2, c1, c2, tmp;
int dfn[5001], low[5001];
int sta[5001], n_n, in[5001];
int num[5001];
bool YES;

void csh() {
    
    
	memset(e, 0, sizeof(e));
	memset(le, 0, sizeof(le));
	KK = 0;
	YES = 1;
	memset(dfn, 0, sizeof(dfn));
	memset(low, 0, sizeof(low));
	memset(sta, 0, sizeof(sta));
	n_n = 0;
	memset(in, 0, sizeof(in));
	memset(num, 0, sizeof(num));
}

int yes(int now) {
    
    
	return now;
}

int no(int now) {
    
    
	return n + now;
}

int change(int now) {
    
    
	if (now <= n) return n + now;
	return now - n; 
}

void add(int x, int y) {
    
    
	e[++KK] = (node){
    
    y, le[x]}; le[x] = KK;
}

void tarjan(int now) {
    
    //Tarjan 缩点
	dfn[now] = low[now] = ++tmp;
	sta[++sta[0]] = now;
	
	for (int i = le[now]; i; i = e[i].nxt)
		if (!dfn[e[i].to]) {
    
    
			tarjan(e[i].to);
			low[now] = min(low[now], low[e[i].to]);
		}
		else if (!in[e[i].to]) low[now] = min(low[now], low[e[i].to]);
	
	if (dfn[now] == low[now]) {
    
    
		in[now] = ++n_n;
		num[n_n]++;
		while (sta[sta[0]] != now) {
    
    
			in[sta[sta[0]]] = n_n;
			num[n_n]++;
			sta[0]--;
		}
		sta[0]--;
	}
	
	return ;
}

int main() {
    
    
	while (scanf("%d", &n) != EOF) {
    
    
		scanf("%d", &m);
		
		csh();//初始化
		
		for (int i = 1; i <= m; i++) {
    
    
			scanf("%d %d %d %d", &a1, &a2, &c1, &c2);
			a1++;
			a2++;
			add(a1 + c1 * n, change(a2 + c2 * n));//建图
			add(a2 + c2 * n, change(a1 + c1 * n));
		}
		
		for (int i = 1; i <= n + n; i++)
			if (!dfn[i]) tarjan(i);
		
		for (int i = 1; i <= n; i++)
			if (in[yes(i)] == in[no(i)]) {
    
    //看是否有矛盾
				printf("NO\n");
				YES = 0; 
				break;
			}
		
		if (YES) printf("YES\n");
	}
	
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43346722/article/details/113837422