Back to Underworld(lightoj 1009)
Time Limit: 4 second(s) | Memory Limit: 32 MB |
The Vampires and Lykans are fighting each other to death. The war has become so fierce that, none knows who will win. The humans want to know who will survive finally. But humans are afraid of going to the battlefield.
So, they made a plan. They collected the information from the newspapers of Vampires and Lykans. They found the information about all the dual fights. Dual fight means a fight between a Lykan and a Vampire. They know the name of the dual fighters, but don't know which one of them is a Vampire or a Lykan.
So, the humans listed all the rivals. They want to find the maximum possible number of Vampires or Lykans.
Input
Input starts with an integer T (≤ 10), denoting the number of test cases.
Each case contains an integer n (1 ≤ n ≤ 105), denoting the number of dual fights. Each of the next n lines will contain two different integers u v (1 ≤ u, v ≤ 20000) denoting there was a fight between u and v. No rival will be reported more than once.
Output
For each case, print the case number and the maximum possible members of any race.
Sample Input |
Output for Sample Input |
2 2 1 2 2 3 3 1 2 2 3 4 2 |
Case 1: 2 Case 2: 3 |
Note
Dataset is huge, use faster I/O methods.
思路:并查集;
我们要把上面的点分成两个阵营,p-q表示p,q这两个点是对立的是不同的阵营,那么我们将每一个点分别构造两个不同的阵营,假如是点P;
那么(p,p+cnt)就为两个不同的阵营的表示法,P-q;也就是p和q+cnt是一个阵营,q和p+cnt是一个阵营,因为p和p+cnt对立,同理。
那么我们就用并差集来合并,然后最后我们可以得到多个集合,并且,其中的每个集合,在这些集合中我们可以找到他的对立集合,所以我们贪心选取,两个集合中最大的那个,加入sum。
(注:每个两个点最多有3种关系,1,同一阵营,2不同阵营,3没有关系)
1 #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 #include<string.h> 5 #include<stdlib.h> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 int du[20005*3]; 10 int str[3*20005]; 11 int flag[3*20005]; 12 typedef struct pp 13 { 14 int x; 15 int y; 16 }ss;ss aa[100005]; 17 map<int,int>my; 18 int main(void) 19 { 20 int n,i,j,k,p,q; 21 int s; 22 scanf("%d",&k); 23 for(s=1;s<=k;s++) 24 { my.clear(); 25 scanf("%d",&n);memset(flag,0,sizeof(flag)); 26 for(i=0;i<3*20005;i++) 27 {str[i]=i;du[i]=1;} 28 int cnt=1; 29 for(i=0;i<n;i++) 30 { 31 scanf("%d %d",&aa[i].x,&aa[i].y); 32 if(my[aa[i].x]==0) 33 my[aa[i].x]=cnt++; 34 aa[i].x=my[aa[i].x]; 35 if(my[aa[i].y]==0) 36 my[aa[i].y]=cnt++; 37 aa[i].y=my[aa[i].y]; 38 } 39 for(i=cnt;i<3*20005;i++) 40 du[i]=0; 41 for(i=0;i<n;i++) 42 { 43 int x=aa[i].x; 44 int y=aa[i].y; 45 int xx=x+cnt-1; 46 int yy=y+cnt-1; 47 int c,c1,c2,c3; 48 for(c=x;str[c]!=c;) 49 c=str[c]; 50 for(c1=y;c1!=str[c1];) 51 c1=str[c1]; 52 for(c2=xx;str[c2]!=c2;) 53 c2=str[c2]; 54 for(c3=yy;c3!=str[c3];) 55 c3=str[c3]; 56 if(c!=c3) 57 { 58 if(du[c]>=du[c3]) 59 { 60 du[c]+=du[c3]; 61 str[c3]=c; 62 } 63 else {du[c3]+=du[c];str[c]=c3;} 64 } 65 if(c1!=c2) 66 { 67 if(du[c2]>=du[c1]) 68 { 69 du[c2]+=du[c1]; 70 str[c1]=c2; 71 } 72 else 73 { 74 du[c1]+=du[c2]; 75 str[c2]=c1; 76 } 77 } 78 }int sum=0; 79 for(i=1;i<cnt;i++) 80 { 81 int c,d; 82 for(c=i;c!=str[c];) 83 {c=str[c];} 84 for(d=i+cnt-1;d!=str[d];) 85 {d=str[d];} 86 if(!flag[c]) 87 { 88 sum+=max(du[c],du[d]); 89 flag[c]=1;flag[d]=1; 90 } 91 } 92 printf("Case %d: %d\n",s,sum); 93 }return 0; 94 }