POJ [2912] Rochambeau 【Sideband rights and check + enumeration】

Description

N children are playing Rochambeau (scissors-rock-cloth) game with you. One of them is the judge. The rest children are divided into three groups (it is possible that some group is empty). You don’t know who is the judge, or how the children are grouped. Then the children start playing Rochambeau game for M rounds. Each round two children are arbitrarily selected to play Rochambeau for one once, and you will be told the outcome while not knowing which gesture the children presented. It is known that the children in the same group would present the same gesture (hence, two children in the same group always get draw when playing) and different groups for different gestures. The judge would present gesture randomly each time, hence no one knows what gesture the judge would present. Can you guess who is the judge after after the game ends? If you can, after how many rounds can you find out the judge at the earliest?

Input 

Input contains multiple test cases. Each test case starts with two integers N and M (1 ≤ N ≤ 500, 0 ≤ M ≤ 2,000) in one line, which are the number of children and the number of rounds. Following are M lines, each line contains two integers in [0, N) separated by one symbol. The two integers are the IDs of the two children selected to play Rochambeau for this round. The symbol may be “=”, “>” or “<”, referring to a draw, that first child wins and that second child wins respectively.

Output 

There is only one line for each test case. If the judge can be found, print the ID of the judge, and the least number of rounds after which the judge can be uniquely determined. If the judge can not be found, or the outcomes of the M rounds of game are inconsistent, print the corresponding message.

Sample Input 

3 3
0<1
1<2
2<0
3 5
0<1
0>1
1<2
1>2
0<2
4 4
0<1
0>1
2<3
2>3
1 0

Sample Output 

Can not determine
Player 1 can be determined to be the judge after 4 lines
Impossible
Player 0 can be determined to be the judge after 0 lines

The main idea:

n people play m rounds of rock-paper-scissors games (0 <n <= 500,0 <= m <= 2000), we know the numbers x, y and results of the two people in each round of the game, but we do n’t know the x, y What is the gesture; one of them is the referee, who can make any gesture. The rest of the people have the same gestures and are divided into three groups. There can be empty groups. That is to say, except for the referee, the gestures of the other people are the same every time. It can be determined at least in the first few rounds.

analysis:

First, we must analyze the output in different situations.

1. If the number of the referee can be uniquely determined, output the number according to the format and the minimum number of rounds that can determine the referee;

2. If there are multiple possible referees but cannot be determined, output Can not determine;

3. If any referee candidate cannot be obtained from the input, then output Impossible; 

Since the referee ’s gestures are random every time, he cannot be fixed in a certain group. With the exception of the referee, others can be surely divided into three groups. In view of the small size of the data in this question, we enumerate each number and try to use it as a referee. Then if there is no contradiction in the relationship between everyone except him, then he may be the referee.

In this way, we can judge three different situations. But for the first case, you need to determine the minimum number of rows required to determine the referee. In the process of our enumeration, once there is a contradiction in the input of a certain line, we determine that the number is not a referee, then the number of the latest contradiction among the n-1 enumerated contradictions is that we can determine The minimum number of lines required by the referee (reaching this line means that all previous lines have been able to exclude all other n-1 numbers, that is, they cannot be referees).

In the process of enumeration, we use sideband weights and check to maintain the relationship between the numbers.

0-parent node and child node belong to the same group

1-The parent node loses to the child node

2-The parent node wins the child node

All operations are performed in the sense of mode 3.

First, the relationship between child nodes, parent nodes, and grand nodes: d [x] (child-to-ye relationship) = (d [x] (child-to-father relationship) + d [y] (father-to-ye relationship)) % 3. This can be obtained by enumerating various situations.

Then, path compression: d [x] (3 to 1 relationship) = d [x] (3 to 2 relationship) + d [y] (2 to 1 relationship))% 3.

When we seek the relationship between any two numbers x, y, we first seek their root node.

1) If the root nodes of the two are the same, it means that we have assigned the relationship of x and y. You only need to verify that the relationship given in the question is in line with the relationship we already have.

Knowing d [x] and d [y] at this time, the relationship from x to y is: (d [x] + (3-d [y]))% 3 (according to the relationship of vector, the inverse of d [y] The weight of the vector is 3-d [y], which can be enumerated to verify) that is, the relationship between x and y is judged to be equal to the question.

2) If the root nodes of the two are different, it means that we have not given the relationship between x and y. Let root1 = find (x), root2 = find (y); .

As shown in the figure, what is sought at this time is e1, d1 = a1 + b1; e1 = d1-c1; e1 = (a1 + b1-c1);

a1 = d [x]; c1 = d [y]; b1 = rel; (the relationship between x and y given in the question)

And -c1 = (3-rel [y])% 3, which has been given before.

In summary: e1 = (d [x] + rel + (3-d [y]))% 3

即d[root2]=(d[x]+rel+3-d[y])%3。

See the code for specific explanation.

#include <iostream>
#include <sstream>
#include <vector>
#include <map>
#include <cstring>
#include <string>
#include <algorithm>

using namespace std;
const int maxn=505;

int n,m;

int fa[maxn],d[maxn];

struct node{
	int x,y;
	char c;
};

vector<node> res;
vector<int> judge;

void init(){
	for(int i=0;i<=n;i++){
		fa[i]=i;
		d[i]=0;
	}
}

int find(int x){
	if(fa[x]==x)  return x;
	int root=find(fa[x]);
	d[x]=(d[fa[x]]+d[x])%3;		//路径压缩 
	return fa[x]=root;
}

int main(){
	char str[25];
	int x,y,rel;
	char c;
	while(cin>>n>>m){
		res.clear();
		judge.clear();
		cin.get();
		for(int i=1;i<=m;i++){
			cin.getline(str,25);
			istringstream in(str);
			node tmp;
			in>>tmp.x>>tmp.c>>tmp.y;
//			cout<<tmp.x<<"  "<<tmp.c<<"  "<<tmp.y<<endl;
			res.push_back(tmp);
		}
		int lst=0;
		for(int i=0;i<n;i++){
			init();		//记得每次枚举都要初始化 
			int flag=0;
			for(int j=0;j<res.size();j++){
				x=res[j].x;
				y=res[j].y;
				c=res[j].c; 
				if(x==i||y==i)  continue;
				if(c=='=')  rel=0;		//父节点和子节点属于同一组 
				else if(c=='<')  rel=1;		//父节点输于子节点 
				else  rel=2;		//父节点赢于子节点 
				
				int fx=find(x),fy=find(y);
				if(fx==fy){
					if((3-d[x]+d[y])%3==rel)  continue;		//同一集合中两者关系的计算 
					else{		//出现矛盾 
						flag=1;
						lst=max(lst,j+1);		//维护出现矛盾的最大行数 
						break;
					}
				}
				else{		//合并操作 
					fa[fy]=fx;
					d[fy]=(d[x]+rel+3-d[y])%3;
				}
			}
			if(flag==0)  judge.push_back(i);		//记录可能的裁判编号 
		}
//		cout<<judge.size()<<endl;
		if(judge.size()==1){
			cout<<"Player "<<judge[0]<<" can be determined to be the judge after "<<lst<<" lines"<<endl;
		}
		else if(judge.size()==0){
			cout<<"Impossible"<<endl;
		}
		else{
			cout<<"Can not determine"<<endl;
		}
	}
	return 0;
} 

 

Published 30 original articles · won 5 · 900 views

Guess you like

Origin blog.csdn.net/qq_42840665/article/details/102655895