HDU3172--Virtual Friends

来源:互联网 发布:视频去黑边软件 编辑:程序博客网 时间:2024/05/19 21:01
Problem Description
These days, you can do all sorts of things online. For example, you can use various websites to make virtual friends. For some people, growing their social network (their friends, their friends' friends, their friends' friends' friends, and so on), has become an addictive hobby. Just as some people collect stamps, other people collect virtual friends.

Your task is to observe the interactions on such a website and keep track of the size of each person's network.

Assume that every friendship is mutual. If Fred is Barney's friend, then Barney is also Fred's friend.

Input
Input file contains multiple test cases.
The first line of each case indicates the number of test friendship nest.
each friendship nest begins with a line containing an integer F, the number of friendships formed in this frindship nest, which is no more than 100 000. Each of the following F lines contains the names of two people who have just become friends, separated by a space. A name is a string of 1 to 20 letters (uppercase or lowercase).

Output
Whenever a friendship is formed, print a line containing one integer, the number of people in the social network of the two people who have just become friends.

Sample Input
13Fred BarneyBarney BettyBetty Wilma

Sample Output
234

 

/*我觉得此题可以用map+并查集此题很坑的地方就是while(scanf("%d",&t)!=EOF){}*/#include <iostream>#include <cstdio>#include <string>#include <map>using namespace std;#define maxn 200008//10万对,最多20万人int father[maxn];int rank1[maxn];int n;map <string,int> coll;void init(){for(int i=1;i<=2*n;i++){father[i]=i;}}int find(int x){if(x==father[x])return x;return father[x]=find(father[x]);}int Union(int a,int b){int aa=find(a);int bb=find(b);rank1[bb]+=rank1[aa]+1;father[aa]=bb;return rank1[bb]+1;}int main(){int t;while(scanf("%d",&t)!=EOF){while(t--){memset(rank1,0,sizeof(rank1));scanf("%d",&n);init();coll.clear();int id=1;for(int i=1;i<=n;i++){string a,b;cin>>a>>b;if(coll[a]&&coll[b])//未必就在同个集合{if(find(coll[a])==find(coll[b])){printf("%d\n",rank1[find(coll[a])]+1);}else printf("%d\n",Union(coll[a],coll[b]));}else if(coll[a]&&!coll[b]){coll[b]=id++;printf("%d\n",Union(coll[a],coll[b]));}else if(!coll[a]&&coll[b]){coll[a]=id++;printf("%d\n",Union(coll[a],coll[b]));}else //两个都没有的话{if(a!=b){coll[a]=id++;coll[b]=id++;father[id-1]=id-2;rank1[id-2]=1;printf("%d\n",2);}else{coll[a]=id++;rank1[id-1]=0;printf("%d\n",1);}}}}}return 0;}


 

 

/*我觉得此题可以用map+并查集好吧。我以为是我的没按秩合并出了问题。还是1250MS。比没按秩合并的还慢50MS。。。STL真心够慢*/#include <iostream>#include <cstdio>#include <string>#include <map>using namespace std;#define maxn 200008//10万对,最多20万人int father[maxn];int rank2[maxn];int rank1[maxn];int n;map <string,int> coll;void init(){for(int i=1;i<=2*n;i++){father[i]=i;}}int find(int x){if(x==father[x])return x;return father[x]=find(father[x]);}int Union(int a,int b){int aa=find(a);int bb=find(b);if(rank1[aa]>rank1[bb]){father[bb]=aa;rank2[aa]+=rank2[bb]+1;return rank2[aa]+1;}else if(rank1[aa]==rank1[bb]){father[bb]=aa;rank1[aa]++;rank2[aa]+=rank2[bb]+1;return rank2[aa]+1;}else{father[aa]=bb;rank2[bb]+=rank2[aa]+1;return rank2[bb]+1;}}int main(){int t;while(scanf("%d",&t)!=EOF){while(t--){memset(rank2,0,sizeof(rank2));memset(rank1,0,sizeof(rank1));scanf("%d",&n);init();coll.clear();int id=1;for(int i=1;i<=n;i++){string a,b;cin>>a>>b;if(coll[a]&&coll[b])//未必就在同个集合{if(find(coll[a])==find(coll[b])){printf("%d\n",rank2[find(coll[a])]+1);}else printf("%d\n",Union(coll[a],coll[b]));}else if(coll[a]&&!coll[b]){coll[b]=id++;printf("%d\n",Union(coll[a],coll[b]));}else if(!coll[a]&&coll[b]){coll[a]=id++;printf("%d\n",Union(coll[a],coll[b]));}else //两个都没有的话{if(a!=b){coll[a]=id++;coll[b]=id++;father[id-1]=id-2;rank2[id-2]=1;printf("%d\n",2);}else{coll[a]=id++;rank2[id-1]=0;printf("%d\n",1);}}}}}return 0;}


 以上两种速度都慢。1200MS。接下来这种用字典树实现映射。200MS

/*用map各种慢~用链表实现字典树我还是很不熟悉*/#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define maxn 200008int cnt,n;//这个就是单词的实际数目和最大数目int father[maxn];int rank1[maxn];struct Node{Node * pr[53];int id;Node() {id=0;for(int i=0;i<=52;i++){pr[i]=NULL;}}}*root;int idx(char c){if(c>='A'&&c<='Z')return c-'A';else return c-'a'+26;}int insert(char *s){int len=strlen(s);Node * p=root;for(int i=0;i<len;i++){int u=idx(s[i]);if(p->pr[u]==NULL){p->pr[u]=new Node();}p=p->pr[u];}if(p->id==0){p->id=cnt++;}return p->id;}//目测成功实现了插入节点了。可以获得这个单词的编号了void init(){for(int i=1;i<=2*n;i++){father[i]=i;}}int find(int x){if(x==father[x])return x;return father[x]=find(father[x]);}int Union(int a,int b){int aa=find(a);int bb=find(b);father[aa]=bb;rank1[bb]+=rank1[aa]+1;return rank1[bb]+1;}void del(Node * p){for(int i=0;i<52;i++){if(p->pr[i])del(p->pr[i]);}delete p;p=NULL;}int main(){int t;while(scanf("%d",&t)!=EOF){scanf("%d",&n);memset(rank1,0,sizeof(rank1));init();root=new Node();char str1[20],str2[20];cnt=1;for(int i=1;i<=n;i++){scanf("%s%s",str1,str2);int a=insert(str1);int b=insert(str2);if(find(a)!=find(b)){printf("%d\n",Union(a,b));}else{printf("%d\n",rank1[find(a)]+1);}}del(root);}return 0;}


 

原创粉丝点击