题面
Background
Professor Hopper is researching the sexual behavior of a rare species of bugs. He assumes that they feature two different genders and that they only interact with bugs of the opposite gender. In his experiment, individual bugs and their interactions were easy to identify, because numbers were printed on their backs.
Problem
Given a list of bug interactions, decide whether the experiment supports his assumption of two genders with no homosexual bugs or if it contains some bug interactions that falsify it.
Input
The first line of the input contains the number of scenarios. Each scenario starts with one line giving the number of bugs (at least one, and up to 2000) and the number of interactions (up to 1000000) separated by a single space. In the following lines, each interaction is given in the form of two distinct bug numbers separated by a single space. Bugs are numbered consecutively starting from one.
Output
The output for every scenario is a line containing “Scenario #i:”, where i is the number of the scenario starting at 1, followed by one line saying either “No suspicious bugs found!” if the experiment is consistent with his assumption about the bugs’ sexual behavior, or “Suspicious bugs found!” if Professor Hopper’s assumption is definitely wrong.
Sample Input
2
3 3
1 2
2 3
1 3
4 2
1 2
3 4
Sample Output
Scenario #1:
Suspicious bugs found!
Scenario #2:
No suspicious bugs found!
Hint
Huge input,scanf is recommended.
题目解释
每组测试数据给定虫子的数量n和m组对立关系,虫子的标号为1到n,每组对立关系表示这两只虫子是异性,想知道这种虫子只有两种性别的推测是否可能成立;
可能成立输出No suspicious bugs found!,不可能则输出Suspicious bugs found!
比如如果前两组数据是1,2 和 2 ,3时,表示1,2是异性,2,3是异性,则1,3是同性,若再给定1,3这组对立关系,则推测不成立
这题大致思路是用并查集实现,用pre数组来记录该集合的根节点,将属于一种性别的虫子放在一个集合里,然后用num数组记录对立关系,counterpart数组记录对立性别的节点;
如果两个虫子的根节点的num不同,则表示它们属于不同的对立关系,若num相同,counterpart不同,则表示属于对立关系的不同性别,若num相同,counterpart相同,则表示是同一性别
所以若是发现有两只虫子num不同,则将他们的根节点连接起来,记得要将一个的根节点与对方根节点的counterpart连接,根节点的counerpart与对方的根节点连接;
若是num相同,而counerpart相同,则出现了矛盾;
注意:
1.每次要对pre数组和num数组进行更新,num存的值为0表示当前这只虫子还不属于任何对立关系
2.记录出现矛盾的状态flag为1,若是flag为1,则不用判断
#include <iostream>
#include <stdio.h>
#include <string.h>
const int maxn = 2002;
int pre[maxn], num[maxn], counterpart[maxn];
int Find(int x)
{
if(x != pre[x])
pre[x] = Find(pre[x]);
return pre[x];
}
int main()
{
int T, n, m;
scanf("%d", &T);
for(int cas = 1; cas <= T; cas++)
{
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++)
{
pre[i] = i;
num[i] = 0;
}
int cur = 1, x, y, flag = 0;
for(int i = 1; i <= m; i++)
{
scanf("%d %d", &x, &y);
if(flag == 1) continue;
x = Find(x); y = Find(y);
if(num[x] == 0 && num[y] == 0)
{
num[x] = num[y] = cur++;
counterpart[x] = y;
counterpart[y] = x;
}
else if(num[x] == 0)
{
pre[x] = counterpart[y];
}
else if(num[y] == 0)
{
pre[y] = counterpart[x];
}
else if(x != y)
{
pre[x] = counterpart[y];
pre[counterpart[x]] = y;
}
else
{
if(counterpart[x] != y)
flag = 1;
}
}
if(cas > 1) putchar('\n');
printf("Scenario #%d:\n", cas);
if(flag == 1) printf("Suspicious bugs found!\n");
else printf("No suspicious bugs found!\n");
}
}
一点收获
1.其实这一题可以用加权并查集的板子去套用,0表示同性,1表示异性,加权完对2取余
1.北大的oj是不可以用万能头文件 #include<bits/stdc++.h>的…
2.这题这题和可以和EOJ上一题配合练习:https://acm.ecnu.edu.cn/problem/1837/