1. 程式人生 > >CodeForces - 445B - DZY Loves Chemistry-轉化問題

CodeForces - 445B - DZY Loves Chemistry-轉化問題

參考 define http 我們 col 只需要 它的 需要 isp

傳送門: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; }
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\n",ans);
    return 0;
}
View Code

CodeForces - 445B - DZY Loves Chemistry-轉化問題