1. 程式人生 > >BZOJ 1370 [Baltic2003]Gang團夥:並查集【虛點】

BZOJ 1370 [Baltic2003]Gang團夥:並查集【虛點】

family sin 一個人 cnblogs href com fin col 不存在

題目鏈接: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 }

BZOJ 1370 [Baltic2003]Gang團夥:並查集【虛點】