【洛谷P1892】團伙
阿新 • • 發佈:2018-11-26
題目大意:維護 N 個人和 M 個關係,對每個人來說符合:我朋友的朋友也是我的朋友,我敵人的敵人也是我的朋友,求最多有多少個朋友構成的聯通塊。
題目大意:維護關係顯然要用到並查集,這裡是維護了兩種關係,即:朋友和敵人,應該有兩種做法,首先是維護帶權並查集,可用 0 表示兩人為朋友,1 表示兩人為敵人,不過這樣做似乎對於求有多少個朋友構成的聯通塊並不容易,因為只要兩個人有關係(無論什麼關係)都在一個聯通塊中;另一種做法就是擴充套件域並查集,將一個點拆成兩個點,分別表示自己朋友的集合和自己敵人的集合,這樣最後統計自己朋友的集合有多少聯通塊直接排序去重即可。
程式碼如下
#include <bits/stdc++.h> using namespace std; const int maxn=1010; int n,m,f[maxn<<1],a[maxn]; char opt[5]; int find(int x){ return x==f[x]?x:f[x]=find(f[x]); } void read_and_parse(){ scanf("%d%d",&n,&m); for(int i=1;i<=n<<1;i++)f[i]=i; } void solve(){ int x,y; while(m--){ scanf("%s%d%d",&opt,&x,&y); if(opt[0]=='F')f[find(x)]=find(y); else f[find(x)]=find(y+n),f[find(x+n)]=find(y); } for(int i=1;i<=n;i++)a[i]=find(i); sort(a+1,a+n+1); printf("%d\n",unique(a+1,a+n+1)-a-1); } int main(){ read_and_parse(); solve(); return 0; }