题目链接:https://hihocoder.com/problemset/problem/1334?sid=1369471
思路:
(1)把单词想象成一个个节点,两个节点若有共同的字母则这两个节点间有一条边,所有节点构成一个图。每个节点有一个度记录该节点与多少个节点相连接,则问题转化为去除最少的节点,使得图中所有节点的度为0;
(2)为了方便统计与节点有共同字母的其他节点,使用unordered_map<char,vector<int>> 的table记录含有字母c的所有字符串的id;
(3)每次寻找度最大的节点,将其度标记为-1,同时将与该节点相连的所有节点度减1;
(4)统计度为0的节点个数。
时间复杂度不会超过O(n^2)
代码如下:
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
#include <unordered_set>
using namespace std;
int main() {
int n;
cin>>n;
vector<unordered_set<int>> g(n);
vector<string> vs;
unordered_map<char,vector<int>> table;
vector<int> degree(n,0);
string s;
for(int i=0;i<n;++i){
cin>>s;
for(auto ch:s)
table[ch].push_back(i);
vs.push_back(s);
}
int maxd=0,idx=-1;
for(int i=0;i<n;++i){
for(auto ch:vs[i])
g[i].insert(table[ch].begin(),table[ch].end());
g[i].erase(i);
degree[i]=g[i].size();
if(degree[i]>maxd){
maxd=degree[i];
idx=i;
}
}
while(idx!=-1){
degree[idx]=-1;
for(auto i:g[idx])
degree[i]--;
idx=-1,maxd=0;
for(int i=0;i<n;++i){
if(degree[i]>maxd){
maxd=degree[i];
idx=i;
}
}
}
int count=0;
for(int i=0;i<n;++i){
if(degree[i]==0)
count++;
}
cout<<count<<endl;
return 0;
}