并查集题目
用map映射的代码跑了1100多ms,而采用trie树保存人名的代码仅跑了203ms。
采用map映射
#include<iostream>
#include<cstdio>
#include<string>
#include<map>
using namespace std;
int root[10010],sign[10010];
map<string,int>list;
int find(int c){
if(root[c]!=c)
root[c]=find(root[c]);
return root[c];
}
void check(int a,int b){
int ra=find(a);
int rb=find(b);
if(ra!=rb){
root[ra]=rb;
sign[rb]+=sign[ra];
}
}
int main(){
string n1,n2;
int n,m;
int len;
while(scanf("%d",&n)!=EOF){
while(n--){
list.clear(); //貌似不加这句就WA
scanf("%d",&m);
if(m==0){
printf("0\n");
continue;
}
len=0;
while(m--){
cin>>n1>>n2;
if(list.find(n1)==list.end()){
root[len]=len;
sign[len]=1;
list[n1]=len++;
}
if(list.find(n2)==list.end()){
root[len]=len;
sign[len]=1;
list[n2]=len++;
}
check(list[n1],list[n2]);
printf("%d\n",sign[find(list[n1])]); //输出不能是cout,否则TLE,汗!
}
}
}
return 0;
}
采用trie树
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
int roott[10010],sign[10010];
int len;
struct node{
node *next[60];
int flag;
node(){
memset(next,NULL,sizeof(next));
flag=0;
}
};
int find(int c){
if(roott[c]!=c)
roott[c]=find(roott[c]);
return roott[c];
}
void check(int a,int b){
int ra=find(a);
int rb=find(b);
if(ra!=rb){
roott[ra]=rb;
sign[rb]+=sign[ra];
}
}
int insert(char *cur,node *root){
node *p=root;
int i=0;
while(cur[i]){
int index=cur[i]-'A';
if(p->next[index]==NULL)
p->next[index]=new node();
p=p->next[index];
i++;
}
if(p->flag!=0)
return p->flag;
else{
p->flag=len;
return 0;
}
}
int main(){
char n1[22],n2[22];
int n,m;
while(scanf("%d",&n)!=EOF){
while(n--){
node *root=new node;
scanf("%d",&m);
if(m==0){
printf("0\n");
continue;
}
len=1;
while(m--){
cin>>n1>>n2;
if(insert(n1,root)==0){
roott[len]=len;
sign[len]=1;
len++;
}
if(insert(n2,root)==0){
roott[len]=len;
sign[len]=1;
len++;
}
//cout<<insert(n1,root)<<insert(n2,root)<<endl;
check(insert(n1,root),insert(n2,root));
printf("%d\n",sign[find(insert(n1,root))]);
}
}
}
return 0;
}