【HDU 3712] Fiolki(右バンドエッジ互いに素なセットヒューリスティックマージ+)

【HDU 3712] Fiolki(右バンドエッジ互いに素なセットヒューリスティックマージ+)

フェイス質問

化学者Jiliは世界を救うために魔法のポーションを設定したいです。
Jiliが異なる液体材料がNであり、およびnのバイアル(1からnまでの平均数)。最初に、ボトルは、i番目のG物質のi番目のG [I]で満たされました。JI Liがシロップを設定するために必要な特定の手順を実行し、i番目のステップは、[I]中のすべての液体がBのボトルに注ぐことである[I]は、ボトルは、その後、最初の[i]は、ボトルではありません使用。ボトル容量は無制限とみなすことができます。
JI Liは、一緒に沈殿する反応液の特定の種、特に反応1グラムC [i]と物質D [i]は2gの物質を生成した沈殿1gを知って、反応が枯渇するまで行われます。いずれかを反応させて得られた沈殿及びません。一緒に反応することができ、複数の物質がある場合、智Liが彼らの反応順序を知っています。それぞれが注ぐ後、Jili次のステップは、反応の終了まで待機します。
Jiliは、総生産の構成プロセスを沈殿させたものを知りたいです。

\(N、Mの\当量2 \回10 ^ 5、k個の\当量5 \回10 ^ 5 \)

分析

ディレクトリは、物質Iとi番目のボトルの初期状態は、それが各物質のみをボトルで起こると言うことであると指摘しました。次いで、混合プロセスは、各反応は、せいぜい1回発生します反応のために\((a、b)は\) 唯一のボトル反応の開始前に、1瓶は、Bがありますので。ときに、Bが出会う、反応の完了まで行われていたであろう。

だから、限り、我々は、i番目の反応の発生時刻を知っているように、反応時間ソートする(同じ優先順位の日時順)。次いで、反応シーケンスのシミュレーション、および沈殿物の品質の更新の反応塊。

(a、b)が起こる反応時間を取得する方法?。当社は、リンクブロック、(b)は、時間に発生した通信における最も早い時刻aとbが同じ物質のビーカーに入れました。接続性を維持するためにばらばらにセットするだけでなく、他の各点を記録してティムをX [x]は、xが父親に接続されて何時間を表します。答えは、パス上のVティムへのuの最大のポイントです。【を特に参照するとコールドBZOJ 4668](+ヒューリスティック互いに素なセットをマージ)

コード

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 200000
#define maxk 500000
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
struct disjoint_set{
    int fa[maxn+5];
    int tim[maxn+5];
    int sz[maxn+5];
    int find(int x){
        while(fa[x]!=x) x=fa[x];
        return x;
    }
    int get_deep(int x){
        int ans=0;
        while(fa[x]!=x){
            ans++;
            x=fa[x];
        }
        return ans;
    }
    void merge(int x,int y,int t){
        int fx=find(x);
        int fy=find(y);
        if(sz[fx]>sz[fy]) swap(fx,fy);
        fa[fx]=fy;
        tim[fx]=t;
        sz[fy]+=sz[fx];
    }
    int query(int x,int y){
        if(find(x)!=find(y)) return INF; 
        int ans=0;
        int dx=get_deep(x),dy=get_deep(y);
        if(dx<dy){
            swap(x,y);
            swap(dx,dy);
        }
        while(dx>dy){
            ans=max(ans,tim[x]);
            x=fa[x];
            dx--;
        }
        if(x==y) return ans;
        while(x!=y){
            ans=max(ans,max(tim[x],tim[y]));
            x=fa[x];
            y=fa[y]; 
        } 
        return ans;
    }
    void ini(int n){
        for(int i=1;i<=n;i++){
            fa[i]=i;
            sz[i]=1;
        }
    }
}S;
int n,m,k;
int g[maxn+5];
struct rec{
    int x;
    int y;
    int tim;
    int id;
    friend bool operator < (rec p,rec q){
        if(p.tim==q.tim) return p.id<q.id;
        else return p.tim<q.tim; 
    }
}q[maxk+5]; 
int main(){
    int u,v;
    scanf("%d %d %d",&n,&m,&k);
    for(int i=1;i<=n;i++){
        scanf("%d",&g[i]);
    } 
    S.ini(n);
    for(int i=1;i<=m;i++){
        scanf("%d %d",&u,&v);
        S.merge(u,v,i);
    }
    for(int i=1;i<=k;i++){
        scanf("%d %d",&q[i].x,&q[i].y);
        q[i].tim=S.query(q[i].x,q[i].y);
        q[i].id=i; 
    }
    sort(q+1,q+1+k);
    ll ans=0;
    for(int i=1;i<=k;i++){
        if(q[i].tim==INF) continue;
        int x=q[i].x,y=q[i].y;
        int sum=min(g[x],g[y]);
        g[x]-=sum;
        g[y]-=sum;
        ans+=sum*2;
    }
    printf("%lld\n",ans);
}

おすすめ

転載: www.cnblogs.com/birchtree/p/11517009.html