codeforces div2 603 D. Secret Passwords

题目大意:

有很多的字符串,如果两个字符串有相同字母,就属于同一组,字符串a与b一组,b与c一组,那么a也与c一组,问这所有字符串可以被分成几组。

思路

我们只需要维护26个小写字母的并查集就可以了。同属于一个字符串里面的所有字母,肯定属于同一个集合中,因为其他任何字符和这个字符串的一个字符相同,那么就和这个字符串所有字符都建立了关系。所以我们只需要把每个字符串相邻两个字符加进一组,最后看26个字母被分成了几组。注意还要定义一个vis[]数组,因为有些字母可能并没有出现。

代码

#include<bits/stdc++.h>
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define debug  freopen("in.txt","r",stdin),freopen("out.txt","w",stdout);
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 1e6+10;
using namespace std;

int N;
int fa[300];
bool vis[300];
void init(){
    for(char c = 'a';c<='z';c++) fa[c] = c;
}
int find(int x){
    return (fa[x] == x)? x: fa[x] = find(fa[x]);
}
void join(int x,int y){
    fa[find(x)] = find(y);
}
int main(){
    ios;
    init();
    cin>>N;
    while(N--){
        string s;cin>>s; 
        for(int i = 1;i<s.length();i++){
            join(s[i-1],s[i]);
        }
        for(auto c:s) vis[c] = 1;
    }
    int cnt = 0;
    for(int i = 'a';i<='z';i++){
        if(vis[i] && find(i) == i) cnt++;
    }
    cout<<cnt<<endl;
    return 0;
}