1. 程式人生 > >小X的液體混合【並查集】

小X的液體混合【並查集】

題目大意:

題目連結:http://10.156.17.250/JudgeOnline/showproblem?problem_id=2476 (學校內網)
-在這裡插入圖片描述


思路:

我們把每種液體看成一個節點,會發生反應的種液體之間連邊。那麼就會出現一張不一定連通的圖。
例如:
在這裡插入圖片描述
我們現在隨便找一個點,把它加入容器中。
在這裡插入圖片描述
那麼可以肯定的是,與這個點連邊的所有點加入到容器中都可以把危險係數乘 2 2 ,那麼就將這些點都放入容器中。
在這裡插入圖片描述


然後再重複剛剛的操作,我們可以發現,一個連通圖中只有第一個放進去的是無法產生貢獻的,而其他都是可以把危險係數乘2的。所以我們就只要判斷有多少個連通圖,這也就說明,有多少個點是不能產生貢獻。那麼剩餘的 n n- 連通圖個數的點都是可以讓答案乘 2
2
的。
那麼就用並查集判斷連通圖個數,然後再高精乘即可。


程式碼:

#include <cstdio>
#include <algorithm>
#define N 1100
#define MAXN 800
using namespace std;

int n,m,x,y,k,t,ans[MAXN+1],father[N];
bool p[N];

int find(int x)
{
	return x==father[x]?x:father[x]=find(father[x]);
}
int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) father[i]=i; for (int i=1;i<=m;i++) { scanf("%d%d",&x,&y); father[find(x)]=find(y); //加入集合 } for (int i=1;i<=n;i++) if (!p[find(i)]) //這個連通圖還沒有被計過 { p[find(i)]=1; k++; //連通圖個數 } ans[MAXN]=1; for (int j=1;j<=n-k;j++) { t=0; for (int i=MAXN;i>=1;i--) { ans[i]=ans[i]*2+t; t=ans[i]/10; ans[i]%=10; } } int i=1; while (!ans[i]) i++; for (;i<=MAXN;i++) printf("%d",ans[i]); return 0; }