前置芝士:并查集
说到义乌普及组2018预赛
我就想起... 那是真的OI两开花。(雾
\(problem↓\)
小白有n个同学,他要开p次聚会,每次他会邀请两个同学参加聚会。并且他知道这n个同学之间的朋友关系,如果a和b是朋友,b和c是朋友,则a和c也是朋友。
给出m对朋友关系,p次聚会,请判断每次被邀请的两个人是否为朋友关系。
Input Data
第一行3个整数n,m,p。分别表示n个同学,m对朋友关系,p次聚会。
接下来n行,每行一个字符串,依次表示每个同学的名字。(字符串长度≤11,且全部位大写字母)
接下来m行,每行两个字符串,用空格隔开,表示为朋友关系的两个人的名字;
接下来p行,每行两个字符串,依次表示每次聚会被邀请的两个人的名字。
Output Data
输出p行,每行一个整数1或者0,其中1表示朋友关系,0表示非朋友关系。
Input / Output Sample
3 1 1
AAA
BBB
CCC
AAA CCC
AAA BBB
0
对于30%的数据1≤n,m,p≤100;
对于50%的数据1≤n,m,p≤1000;
对于100%的数据1≤n,m,p≤2000;
一年前刚学OI 只会用数组。 而一年后 回过来做这题。 觉得特简单
(优越感油然而生)
emmm 废话不多。 这题就是个板子。(而且还是个并查集板子)
重要的是怎么储存这个编号 然后并查集。
不难想。我们可以用\(MAP\)吖。
这样就很简单了。
//并查集板子
inline int find(int x) {
return fa[x] == x ? fa[x] : fa[x] = find(fa[x]) ;
}
inline void merge(int x,int y) {
fa[find(x)] = find(y) ;
}
完整代码
#ifdef Dubug
#endif
#include
using namespace std;
typedef long long LL ;
inline LL In() { LL res(0),f(1); register char c ;
while(isspace(c=getchar())) ; c == '-'? f = -1 , c = getchar() : 0 ;
while(res = (res << 1) + (res << 3) + (c & 15) , isdigit(c=getchar())) ;
return res * f ;
}
map mp ;
const int N = 2000 + 5 ;
int n , m , p ;
int fa[N] ;
inline int find(int x) {
return fa[x] == x ? fa[x] : fa[x] = find(fa[x]) ;
}
inline void merge(int x,int y) {
fa[find(x)] = find(y) ;
}
signed main () {
ios::sync_with_stdio(false) ;
cin >> n >> m >> p ;//n = In() , m = In() , p = In() ;
for(register int i=1;i<=N;i++) fa[i] = i ;
for(register int i=1;i<=n;i++) {
string s ; cin >> s ;
mp[s] = i ;
}
for(register int i=1;i<=m;i++) {
string s1 , s2 ; cin >> s1 >> s2 ;
merge(mp[s1],mp[s2]) ;
}
for(register int i=1;i<=p;i++) {
string s1 , s2 ; cin >> s1 >> s2 ;
puts(find(mp[s1]) == find(mp[s2])?"1":"0") ;
}
return 0 ;
}