老头马桶枪!
Time Limit: 1000 MS Memory Limit: 64 MB
众所周知,集训队的题目是非常困难的。因此,队员们在挂机AK之后,常常会玩一些游戏。
这次,率先AK的周大爷想出了一个叫老头马桶枪的游戏。
在一个小岛上,有三个物种,一共N个生物生活在一起,他们分别是老头、马桶和枪。他们之间的关系是相互克制的,就像包剪锤一样。老头克制马桶,马桶克制枪,枪又克制老头。
现在,集训队的三名成员,小周,小钱和小胡按次序(周、钱、胡)轮流给出信息,信息有两种形式:
第一种记录方式是1 X Y
是同类。
第二种记录方式是2 X Y
,表示 X对 Y有攻击性行为( X克制 Y)。
当其中一人给出的信息和之前的人给出的信息矛盾时,他便输了,要请吃晚饭。那么,聪明的你能帮助他们看出谁会输呢?(最多只会有一个人输,当多条信息矛盾时,最先给出矛盾信息的人输)
Input
第一行包含两个整数N
Output
输出一行,表示最先给出矛盾信息的人是谁。若是小周,输出1
;若是小钱,输出2
;若是小胡,输出3
;若没有人给出矛盾信息,输出-1
。
Sample input and output
Sample Input | Sample Output |
---|---|
100 7 1 100 1 2 1 2 2 2 3 2 3 3 1 1 3 2 3 1 1 5 5 |
1 |
Source
UESTC Online Judge
Copyright (C) 2012 - 2018 Ruins He(@ruinshe), Jianjin Fan(@pfctgeorge) and Yun Li(@mzry1992). Project home
Any Problem, Please Report On Issues Page.
这一题仿照poj1182的食物链https://blog.csdn.net/keepcoral/article/details/79946060
食物链循环,a->b,b->c,c->a,这里学到一种新的方法,上面写的实在有点难懂,特别是推到关系那里,真的很难想,这里从别人博客上学到了新方法。
首先,有n个动物,那么我们开辟3n个集合,x,x+n,x+2n,分别表示与x同类,被x吃的,吃x的集合,所以两个动物x和y下面有两种情况:
1 x和y是同类,那么和y同类的即等价于和x同类,吃y的等价于吃x的,被y吃的等价于被x吃的,所以这三个集合要同时合并,
Union(x,y);
Union(x+n,y+n);
Union(x+2*n,y+2*n)
判断真假条件:x被y吃||x吃y,那么直接表示就是x在y+n的集合||x在y+2n的集合,这里y+n代表被y吃的集合,y+2n代表吃y的集合,所以判断条件为judge(x,y+n)&&judge(x,y+2n),
2 x吃y,那么被y吃的等价于吃x的,和y同类的等价于被x吃的,吃y的等价于x的同类,所以集合为
Union(x,y+n);
Union(x+n,y+2*n);
Union(x+2*n,y);
判断真假条件:x和y同类||y吃x,所以条件为 judge(x,y)&&judge(x,y+n)(我的代码可能会有点出入,因为n和2*n我写的恰好相反的)
这里的合并是最关键的操作,下面的几道题也是一样,也就是当不知道情况的时候才可以去合并,这是题目的要求
#include<iostream>
#include<string>
#include<vector>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<set>
#include<stack>
#include<queue>
#include<string>
#include<map>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
int father[300009];
int Find(int x)
{
if(x!=father[x]) father[x]=Find(father[x]);
return father[x];
}
int Union(int x,int y)
{
int i=Find(x);
int j=Find(y);
if(i!=j) father[i]=j;
}
int judge(int x,int y)
{
int i=Find(x);
int j=Find(y);
if(i!=j)//不同类
{
return 1;
}
else return 0;
}
int main()
{
int n,m,i,j,k;
scanf("%d%d",&n,&m);
for(i=1;i<=3*n;i++) father[i]=i;
for(i=1; i<=m; i++)
{
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==1)//x和y是同类,所以判断不同类
{
if(judge(x,y+n)&&judge(x,y+2*n))
{
Union(x,y);
Union(x+n,y+n);
Union(x+2*n,y+2*n);
}
else
{
if(i%3!=0)printf("%d\n",i%3);
else printf("3\n");
break;
}
}
else//x吃y,要判断同类或者y吃x
{
if(judge(x,y)&&judge(x,y+2*n))
{
Union(x,y+n);
Union(x+n,y+2*n);
Union(x+2*n,y);
}
else
{
if(i%3!=0)printf("%d\n",i%3);
else printf("3\n");
break;
}
}
}
if(i==m+1) printf("-1\n");
return 0;
}
I - 不如把并查集加上个计数功能吧
Time Limit: 1000 MS Memory Limit: 64 MB
在另一个宇宙,一个月有 N
天一样。
但民众并不满足于此,他们想知道有多少天的天气和第 X
天一样。现在,作为一个聪明的程序员,你能帮他们解决这个问题吗?
Input
第一行包含两个整数N