CodeForces - 445B - DZY Loves Chemistry-转化问题

传送门:http://codeforces.com/problemset/problem/445/B

参考:https://blog.csdn.net/littlewhite520/article/details/77018559

题意:

  有N种药剂编号 1 ~ N,然后有M种反应关系,这里有一个试管,开始时危险系数为 1,每当放入的药剂和瓶子里面的药剂发生反应时危险系数会乘以2,(注意,不管会发生反映的有几组,只要在同一次加入的,只乘一个2;)否则就不变,给出N个药剂和M种反应关系,求最大的危险系数。

思路:这个思路是真的优秀,感觉是一种逆向思维:

  我们假设 1 ~ N 有 M 种反应关系 ,如果有反应关系的我们可以把他们看成是一个集合 ,假设这M种反应构成了 T个集合,那么把这T个集合中的元素依次放入试管,有几个不发生反应呢?当然是T个了,把每个集合看成是一课树,根节点和其子节点反应,这个子节点又和它的子节点发生反应、想一想是一个链状的结构、、、假设每个集合放入时先放根节点(第一个节点),那么每个根节点是不是都不和当前试管中的药剂发生反应呢,因为根节点只和它的子节点发生发应,而他的子节点尚未放入、、所以把这些药剂全部放入,最少只需要 T 个不发生发应。

  至于找集合的个数,可以用并查集或者dfs;

dfs的:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define pb push_back
typedef long long ll;
using namespace std;
const int maxn =  55;

vector<int>mp[maxn];
int vis[maxn];
void dfs(int v)
{
    vis[v] = 1;
    for(int i=0;i<mp[v].size();i++)
    {
        int tmp = mp[v][i];
        if(vis[tmp]==0)
        {
            dfs(tmp);
        }
    }
    return ;
}

int  main(){
    int n,m;
    scanf("%d%d",&n,&m);
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        mp[a].pb(b);
        mp[b].pb(a);
    }
    ll ans = 1;
    int t = 0;
    for(int i=1;i<=n;i++)
    {
        if(vis[i]==0)
        {
            dfs(i);
            t++;
        }
    }
    t = n - t;
    for(int i=1;i<=t;i++)
    {
        ans*=2;
    }
    printf("%lld\n",ans);
    return 0;
}

并查集:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn = 55;
int n,m;
int fa[maxn];
void init(){
    for(int i=1;i<=n;i++)
        fa[i]=i;
}
int finx(int x)
{
    if(fa[x]==x)return x;
    else return fa[x] = finx(fa[x]);
}
void uni(int x,int y)
{
    int px = finx(x);
    int py = finx(y);
    if(px==py)return ;
    else fa[px] = py;
}
int main(){
    scanf("%d%d",&n,&m);
    init();
    for(int i=1;i<=m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        uni(a,b);
    }
    int t=0;
    for(int i=1;i<=n;i++)
        if(fa[i]==i)t++;
    t = n - t;
    long long ans = 1;
    for(int i=1;i<=t;i++)
    {
        ans *= 2;
    }
    printf("%lld\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/ckxkexing/p/8719762.html

时间: 2024-10-09 01:55:39

CodeForces - 445B - DZY Loves Chemistry-转化问题的相关文章

Codeforces 445B DZY Loves Chemistry(并查集)

题目链接:Codeforces 445B DZY Loves Chemistry 题目大意:有若干种化学药品,给出两两会反应的关系,现在要将药物依次放入一个容器中,容器中的化学药品可以互相反应,如果当前放入的药品能与已经在容器中的某一药品反应,那么危险值翻倍,即*2,初始值为1,求一顺序,使得为危险值最大. 解题思路:并查集求最小联通分量s,2n?s即为答案. #include <cstdio> #include <cstring> #include <iostream>

CodeForces 445B DZY Loves Chemistry

DZY Loves Chemistry Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 445B Description DZY loves chemistry, and he enjoys mixing chemicals. DZY has n chemicals, and m pairs of them will re

CodeForces 445B. DZY Loves Chemistry(并查集)

转载请注明出处:http://blog.csdn.net/u012860063?viewmode=contents 题目链接:http://codeforces.com/problemset/problem/445/B --------------------------------------------------------------------------------------------------------------------------------------------

Codeforces Round #254 (Div. 2) B. DZY Loves Chemistry (并查集)

题目链接 昨天晚上没有做出来,刚看题目的时候还把题意理解错了,当时想着以什么样的顺序倒,想着就饶进去了, 也被题目下面的示例分析给误导了. 题意: 有1-n种化学药剂  总共有m对试剂能反应,按不同的次序将1-n种试剂滴入试管,如果正在滴入的试剂能与已经滴入 的试剂反应,那么危险数*2,否则维持不变.问最后最大的危险系数是多少. 分析:其实这个题根本不用考虑倒入的顺序,只是分块就行,结果就是每个子集里元素的个数-1 和  的2的幂. 1 #include <iostream> 2 #inclu

Codeforces Round #254 (Div. 2) DZY Loves Chemistry【并查集基础】

一开始不知道题意是啥意思,迟放进去反应和后放进去反应有什么区别 对于第三组数据不是很懂,为啥312,132的组合是不行的 后来发现这是一道考察并查集的题目 QAQ 怒贴代码: 1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <math.h> 5 #include <iostream> 6 #include <algorithm> 7

Codeforces 444A DZY Loves Physics(图论)

题目链接:Codeforces 444A DZY Loves Physics 题目大意:给出一张图,图中的每个节点,每条边都有一个权值,现在有从中挑出一张子图,要求子图联通,并且被选中的任意两点,如果存在边,则一定要被选中.问说点的权值和/边的权值和最大是多少. 解题思路:是图论中的一个结论,最多两个节点,所以枚举两条边就可以了.我简单的推了一下,2个点的情况肯定比3个点的优. 假设有3个点a,b,c,权值分别为A,B,C 现a-b,b-c边的权值分别为u,v 那么对于两点的情况有A+Bu,B+

Codeforces 444B DZY Loves FFT(概率)

题目连接:Codeforces 444B DZY Loves FFT 题目大意:根据题目的算法生成a,b数组,然后对于每个长度的l,求a[i]*b[l-i]的最大值. 解题思路:概率问题,枚举前30大的数,如果有就可以直接输出答案,如果没有,就暴力枚举b数组为1的位置找最大值. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long

codeforces 446C DZY Loves Fibonacci Numbers(数学 or 数论+线段树)

In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation F1 = 1; F2 = 1; Fn = Fn - 1 + Fn - 2 (n > 2). DZY loves Fibonacci numbers very much. Today DZY gives you an array consisting of n integers: a1, a2, ...,

Codeforces 444C DZY Loves Colors(线段树)

题目大意:Codeforces 444C DZY Loves Colors 题目大意:两种操作,1是修改区间上l到r上面德值为x,2是询问l到r区间总的修改值. 解题思路:线段树模板题. #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; const int maxn = 5*1e5; typedef long lo