題目連結:http://www.lydsy.com/JudgeOnline/problem.php?id=1370
題意:
在某城市裡住著n個人,任何兩個認識的人不是朋友就是敵人,而且滿足:
(1)我朋友的朋友是我的朋友。
(2)我敵人的敵人是我的朋友。
所有是朋友的人組成一個團伙。
告訴你關於這n個人的m條資訊,即某兩個人是朋友,或者某兩個人是敵人。
請你編寫一個程式,計算出這個城市最多可能有多少個團伙。
題解:
對於一個人a,建兩個點a和a+n。
a+n實際上並不存在,只起到連線的作用,是一個虛點。
所有與a相連的點都是a的朋友。
所有與a+n相連的點都是它的敵人。
如果x和y是朋友,則合併(x,y)。
如果x和y是敵人,則合併(x,y+n)和(y,x+n)。
所有在一個集合內的人,都屬於同一個團伙。
統計一下有多少個集合,至少包含一個在[1,n]內的點,即為答案。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define MAX_N 2005 5 6 using namespace std; 7 8 int n,m; 9 int ans=0; 10 int par[MAX_N]; 11 bool vis[MAX_N]; 12 13 void init_union_find() 14 { 15 for(int i=1;i<=n*2;i++) 16 { 17 par[i]=i; 18 } 19 } 20 21 int find(int x) 22 { 23 return par[x]==x?x:par[x]=find(par[x]); 24 } 25 26 void unite(int x,int y) 27 { 28 int px=find(x); 29 int py=find(y); 30 if(px==py) return; 31 par[px]=py; 32 } 33 34 bool same(int x,int y) 35 { 36 return find(x)==find(y); 37 } 38 39 void read() 40 { 41 cin>>n>>m; 42 init_union_find(); 43 int x,y; 44 char p; 45 for(int i=0;i<m;i++) 46 { 47 cin>>p>>x>>y; 48 if(p=='F') unite(x,y); 49 else 50 { 51 unite(x+n,y); 52 unite(y+n,x); 53 } 54 } 55 } 56 57 void solve() 58 { 59 memset(vis,false,sizeof(vis)); 60 for(int i=1;i<=n;i++) 61 { 62 int p=find(i); 63 if(!vis[p]) 64 { 65 vis[p]=true; 66 ans++; 67 } 68 } 69 } 70 71 void print() 72 { 73 cout<<ans<<endl; 74 } 75 76 int main() 77 { 78 read(); 79 solve(); 80 print(); 81 }