Problem Description
现有M
个人一起玩剪刀石头布,以1
-M
编号,每人出一种,出过不再改变,但是我们并不知道它到底是哪一种。
(其中石头赢剪刀,剪刀赢布,布赢石
头,一样则平)
裁判用两种说法对这M
个人所构成的输赢关系进行描述:
一:"1 A B",表示第A个人和第B个人出的一样。
二:"2 A B",表示第A个人赢第B个人。
裁判对M个人,用以上两种说法,连说N句话,其中有真的、也有假的。
3)该句话表示A赢A。
请根据给定的M和N,输出假话数。其中(1<= M<=10,000),(0<= N <= 10,000)
Input
第1行是一个自然数K,代表有K组数据。
每组数据以一个空行分隔,其中每组数据的第1行是两个自然数M、N,以空格分开。
每组数据的第2行至N+1行,每行是三个自然数X,A,B,三个数之间用空格分开,X(1或2)表示说法的种类。
Output
现有M
个人一起玩剪刀石头布,以1
-M
编号,每人出一种,出过不再改变,但是我们并不知道它到底是哪一种。
(其中石头赢剪刀,剪刀赢布,布赢石
头,一样则平)
裁判用两种说法对这M
个人所构成的输赢关系进行描述:
一:"1 A B",表示第A个人和第B个人出的一样。
二:"2 A B",表示第A个人赢第B个人。
裁判对M个人,用以上两种说法,连说N句话,其中有真的、也有假的。
一句话出现以下情况,就是假话,否则就是真话。
1) 该句话与之前的某些真话冲突;
2)该句话中A或B比M大;3)该句话表示A赢A。
请根据给定的M和N,输出假话数。其中(1<= M<=10,000),(0<= N <= 10,000)
Input
第1行是一个自然数K,代表有K组数据。
每组数据以一个空行分隔,其中每组数据的第1行是两个自然数M、N,以空格分开。
每组数据的第2行至N+1行,每行是三个自然数X,A,B,三个数之间用空格分开,X(1或2)表示说法的种类。
Output
每组数据对应一行,每行有一个整数,代表假话数。
sample input
3
43 11
1 4 3
2 3 3
1 4 1
1 4 4
2 3 3
1 2 2
2 1 4
1 1 1
2 1 4
2 3 4
2 3 2
66 9
2 3 1
2 4 4
2 1 2
2 4 3
2 4 2
2 2 3
1 3 2
1 2 1
1 1 1
6 7
2 3 7
2 1 2
2 4 4
1 2 1
1 3 2
1 2 3
2 1 3
sample output
5
4
3
建一个图,如果A win B, 则A 到 B的边权为1, 而B到A的边权为2;如果A draw B, 则A 到 B的边权为0, B到A的边权为0。 每次输入一句话则搜索两者是否边连通,如果不连通则加边;如果连通,则看两者的距离MOD 3的值, 如果MOD 3 得1则前者胜后者,得0则平,得2 则后者胜前者。比如说A胜B, B 胜 C, 则可知C胜A,那么A->B = 1, B->A = 2, B->C = 1, C->B = 2,那么可推出A->C = 2:A->B + B->C = 2 , 或者C->A = C->B + B->A = 4 mod 3 =1;同者都说明C win A。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<cmath>
#include<string>
using namespace std;
struct Edge
{
int v, next, f;
}e[20000];
int g[20000];
int num;
void addedge(int a, int b, int f)
{
e[++num].v = b;
e[num].next = g[a];
e[num].f = f;
g[a] = num;
}
int vis[10000];
int dfs(int a, int b)
{
int i, ret = 0;;
for(i = g[a]; i; i = e[i].next)
{
int v = e[i].v;
if(v == b)
return e[i].f;
if(vis[v])
{
vis[i] = 0;
ret = dfs(v, b);
vis[a] = 1;
}
if(ret >= 0)return e[i].f + ret;
}
return -1;
}
int main()
{
int n, m;
int i, j, k;
int cnt;
int t;
int a, b, q;
scanf("%d", &t);
while(t--)
{
int bf = 0;
cnt = 0;
int flag = 0;
scanf("%d%d", &m, &n);
num = 0;
for(int i = 0; i <= 2 * n; i++)e[i].f = -1;
memset(g, 0, sizeof(g));
memset(vis, 1, sizeof(vis));
while(n--)
{
scanf("%d%d%d", &q, &a, &b);
if(q == 1)
{
if(a == b)continue;
vis[a] = 0;
int dis = dfs(a, b);
vis[a] = 1;
if(dis == -1)
{
addedge(a, b, 0);
addedge(b, a, 0);
}
else if(dis % 3 != 0)
cnt ++;
}
if(q == 2)
{
if(a == b || a > m || b > m)
{
cnt ++;
continue;
}
vis[a] = 0;
int dis = dfs(a, b) % 3;
vis[a] = 1;
if(dis != -1 && dis != 1)cnt ++;
if(dis == -1)
{
addedge(a, b, 1);
addedge(b, a, 2);
}
}
}
printf("%d\n", cnt);
}
return 0;
}