小X的液體混合【並查集】
阿新 • • 發佈:2018-11-10
題目大意:
題目連結:http://10.156.17.250/JudgeOnline/showproblem?problem_id=2476 (學校內網)
-
思路:
我們把每種液體看成一個節點,會發生反應的種液體之間連邊。那麼就會出現一張不一定連通的圖。
例如:
我們現在隨便找一個點,把它加入容器中。
那麼可以肯定的是,與這個點連邊的所有點加入到容器中都可以把危險係數乘
,那麼就將這些點都放入容器中。
然後再重複剛剛的操作,我們可以發現,一個連通圖中
只有第一個放進去的是無法產生貢獻的,而其他都是可以把危險係數乘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;
}