zoukankan      html  css  js  c++  java
  • CodeForces

    传送门: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
    ",ans);
        return 0;
    }
    View Code

    并查集:

    #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
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    A 开场白 快速幂
    矩阵快速幂
    围棋棋盘有多少正方形 19*19
    matlab
    汉诺塔问题
    error C2504 base class undefined
    查看标准的FM以及描述等的一个数据…
    报表整合数据的时候,常见的模式:
    SQL执行顺序
    LIST&nbsp;BOX&nbsp;联动的实现
  • 原文地址:https://www.cnblogs.com/ckxkexing/p/8719762.html
Copyright © 2011-2022 走看看