Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 38608 | Accepted: 11887 |
Description
Input
Output
Sample Input
1 5 5 A 1 2 D 1 2 A 1 2 D 2 4 A 1 4
Sample Output
Not sure yet. In different gangs. In the same gang.
题目大意:
这个城市有两股恶势力,一共有N个人,警察只知道这N个人中的部分的线索(线索是不完整的),线索只知道M条,要求通过线索,判断这两个人是否是属于同一股势力的。
遇到的问题和思路:
本来以为这道题目是简单的TAT,结果刚开始的思路错了,纠正了我好久。然后这道题的最难点就是在于,如果前面给你的所有的人之间都是有联系的,然后这些人可以通过树连在一起,但是,如果后来突然有一组数据给你两个人和前面的所有人毫无关系,那会怎么办(就在这里卡主了TAT)。
看了一下别人的题解,是用另外一个数组来联系着两个人。首先这两个人如果是敌对势力,那么就创定一个数组foe,然后让foe[a] = b, foe[b] = a,就说明这两个人是敌对关系,用这一组数组,既保存了敌对关系的数据,又为又来判断关系提供了一个依据。
给出AC代码:
#include<cstdio> #include<cstring> using namespace std; const int MAX = 150000 + 5; int n, m, a, b; char ch; int par[MAX], foe[MAX], rank[MAX]; void inti(){ for(int i = 0; i < MAX; i++){ par[i] = i; foe[i] = 0; rank[i] = 0; } return ; } int find(int a){ if(par[a] == a)return a; else return par[a] = find(par[a]); } void unite(int x, int y){ x = find(x); y = find(y); if(x == y) return ; if(rank[x] < rank[y]){ par[x] = y; } else { par[y] = x; if(rank[x] == rank[y]){ rank[x]++; } } } int same(int x, int y){ return find(x) == find(y); } void solve(){ scanf("%d%d", &n, &m); getchar(); //if(n == 2 && m >= 1){printf("In different gangs.\n");return ;} inti(); for(int i = 0; i < m; i++){ scanf("%c%d%d", &ch, &a, &b); getchar(); if(ch == 'D'){ if(foe[a])unite(foe[a], b); if(foe[b])unite(foe[b], a); foe[b] = a; foe[a] = b; } else { if(same(a, foe[b])) printf("In different gangs.\n"); else if(same(a, b))printf("In the same gang.\n"); else printf("Not sure yet.\n"); } } return ; } int main(){ int t; scanf("%d",&t); getchar(); while(t--){ solve(); } return 0; }
给出测试数据:
/*
3
5 5 A 1 2 D 1 2 A 1 2 D 2 4 A 1 4//原题的
5 7
A 1 2
D 1 2
A 1 2
not sure yet.
D 2 4
A 1 4
in different gangs
D 3 5
A 1 5
not sure yet.
4 4
D 1 2
D 3 4
D 1 4
A 1 3
ans : In the same gang.
2 1
A 1 2
ans : In different gangs.或者是not sure yet 都能AC,例如我的AC代码注释掉的那句
*/