[题解]小X的液体混合

版权说明:来自 石门ss学校 Guohao OJ ,禁止转载

题目描述

虽然小X不喜欢化学原理,但他特别喜欢把一大堆液体倒在一起。

现在小X有n种液体,其中m对会发生反应。现在他想把这n种液体按某种顺序倒入一个容器内,让他获得最刺激的体验,也就是使危险系数尽量大。

我们可以这样计算危险系数,一开始容器内没有任何液体,危险系数为1。每次液体倒入容器时,若容器内已有一种或多种液体会与这种液体发生反应,则危险系数会乘2,否则危险系数不变。

最大危险系数小X不会算,希望你帮帮他。

输入输出格式

输入格式:

第一行包含两个整数n,m。

接下来m行,每行包含两个整数a,b,表示液体a和液体b会发生反应。

输出格式:

一行,包含一个整数,表示最大危险系数。

输入输出样例

输入样例:
3 2
1 2
2 3
输出样例:
4

说明

数据规模:

对于30%的数据,n≤10;

对于100%的数据,1≤n≤1000,a≠b,同种反应不会出现多次。

 

题目分析:

通过题目可以发现,不用管放置的顺序,我们就可以轻而易举得想到并查集,将液体合并为后,一个集的危险指数就为  2 的 (集合内个数-1) ,最后将所有集合值加起来就是答案。

 

代码

 1 #include<iostream>
 2 #include<fstream>
 3 using namespace std;
 4 typedef string str;
 5 const int Max_N=1e3+5;
 6 int n,m;
 7 int Fa[Max_N],tot[Max_N];
 8 string mul(string s1,string s2)
 9 {
10 //    一连串的高精度乘法,个人码风问题不建议借鉴
11 //     最好自己手写一个
12     #define len1 (s1.size())
13     #define len2 (s2.size())
14     int maxx=max(len1,len2);
15     register int i,j,k,l;
16     int Ans[maxx<<1|1];
17     for(i=0;i<=(maxx<<1);i++)Ans[i]=0;
18     for(i=0;i<len1;i++)s1[i]-='0';
19     for(i=0;i<len2;i++)s2[i]-='0';
20     for(i=len1-1,k=0;i>=0;i--,k++){
21         for(j=len2-1,l=(maxx<<1)-k;j>=0;j--,l--)
22             Ans[l]+=(int)s1[i]*s2[j];        
23     }
24     for(i=(maxx<<1);i>=0;i--)
25         if(Ans[i]>9){
26             int xy=Ans[i]/10;
27             Ans[i-1]+=xy;
28             Ans[i]%=10; 
29         }
30     int top=0;
31     while(Ans[top]==0&&top^(maxx<<1))top++;
32     string res;
33     for(i=top;i<=maxx<<1;i++)res+=Ans[i]+'0';
34     return res;
35 }
36 int Find(int p)
37 {
38 //    查询祖先
39     if(Fa[p]==p)
40         return p;
41     return Fa[p]=Find(Fa[p]);
42 }
43 void megre(int u,int v)
44 {
45     Fa[Find(u)]=Fa[Find(v)];
46     return ;
47 }
48 str Pow(str b,int p)
49 {
50 //    字符串版快速幂:-D
51     if(!p)
52         return "1";
53     str res="1";
54     while(p){
55         if(p&1)
56             res=mul(res,b);
57         b=mul(b,b);
58         p>>=1;
59     }
60     return res;
61 }
62 int main()
63 {
64     scanf("%d%d",&n,&m);
65     int u,v;
66     register int i,j;
67     for(i=1;i<=n;i++)    
68         Fa[i]=i;
69     for(i=1;i<=m;i++){
70         scanf("%d%d",&u,&v);
71         megre(u,v);//²¢²é¼¯ºÏ²¢²Ù×÷ 
72     }        
73     for(i=1;i<=n;i++)
74         tot[Find(i)]++;//统计集合内个数
75     str res="1";
76     for(i=1;i<=n;i++)
77         if(tot[i]>1)
78             res=mul(res,Pow("2",tot[i]-1));
79 //    答案为集合内的 pow(2,(集合内个数-1)) 的和
80     cout<<res;
81     return 0;
82 }
代码

 

写在最后的话:

题解仅供思路,要想成为 dalao ,请学会并尽量会做到教他人甚至自己写题解。

博主(目前)是一名初二蒟蒻,如有问题还请大家指出,一起交流学习!

Happy every day!        ——2019.4.11

 

转载于:https://www.cnblogs.com/lihepei/p/10691646.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值