1553:〔実施例2〕鎖暗いです

1553:〔実施例2〕鎖ダーク

期限:1000ミリ秒のメモリの制限:524288キロバイト

タイトル説明

POJ 3417:からオリジナルタイトル

ダーク図、N個のノードと2つのエッジに無向グラフであり、1側は、主要エッジと呼ばれ、他のタイプは、追加のサイドと呼ばれます。

N-1ダーク条主要な側面があり、暗の任意の2つのノード間の唯一の主切れ刃からなる経路が存在します。

また、暗いだけでなく、追加のエッジのM個。

あなたの仕事は暗いが切断二つの部分にカットすることです。

追加サイドのダーク初めは無敵状態で、あなただけの主切刃のいずれかを選択することができます。

あなたが主要なエッジをカットすると、ダークは守備のモードになり、メイン側が無敵になり、追加のエッジを遮断することができます。しかし、あなたはその後、ダークサイドを追加する機能を遮断することができます。


今、あなたが知りたい、プログラムの種類の数はダークを倒すことができますがあります。

注最初のステップの後にあなたがメインのダークサイドを遮断しても、という二つの部分にカットしていた、あなたはまた、追加的な敗北闇の最先端を考慮する必要があります。

[入力]

最初の行は、2つの整数N及びMを含み、

N-1行、それぞれ含む二つの整数AとBは、AとBとの間の主要なエッジを発現した後に、

M行を同じ形式で指定された後追加の側面。

[出力]

出力は、整数回答を表します。

[サンプル]入力

4 1
1 2
2 3
1 4
3 4

[サンプル]出力

3

[注]

データ範囲注:

20%のデータ、1≤N、M≤100;

100%1のデータ≤N≤\(1 * 10 ^ { 5} \)、1≤M≤\(2 * 10 ^ {5} \)。

回答データは\超えない(2 ^ {31} -1 \)が保証されています。

 

[説明]

 

各主要エッジの列挙を考慮すると、削除した後に、この場合、元のツリーを2つに分割された後に削除され、追加の中間のエッジ場合、ANS + M、一つだけ二場合以上、削除することができます解決策はありません。

 

いくつかの主要な側面に追加の各エッジの寄与を分析する、唯一の2つのエンドポイント間の彼の道を見つけるために貢献しています。

 

木や木のチェーンは差が解消することができます分割されます。

 

コードは以下の通りであります:

 

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,last[N],size,f[N][20],dep[N],cha[N];
struct pigu
{
    int dao,ne;
}a[N<<1];
inline void lingjiebiao(int x,int y)
{
    a[++size].dao=y;
    a[size].ne=last[x];
    last[x]=size;
}
inline void dfs1(int now,int fa)
{
    f[now][0]=fa;dep[now]=dep[fa]+1;
    for(int i=1;f[f[now][i-1]][i-1];i++) f[now][i]=f[f[now][i-1]][i-1];
    for(int i=last[now];i;i=a[i].ne)
    {
        if(a[i].dao==fa) continue;
        dfs1(a[i].dao,now);
    }
}
inline int get_lca(int x,int y)
{
    if(dep[x]<dep[y]) swap(x,y);
    for(int i=19;i>=0;i--) if(dep[x]-(1<<i)>=dep[y]) x=f[x][i];
    if(x==y) return x;
    for(int i=19;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    return f[x][0];
}
inline void dfs2(int now)
{
    for(int i=last[now];i;i=a[i].ne)
    {
        if(f[now][0]==a[i].dao) continue;
        dfs2(a[i].dao);
        cha[now]+=cha[a[i].dao];
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1,x,y;i<=n-1;i++)
    {
        scanf("%d%d",&x,&y);
        lingjiebiao(x,y);
        lingjiebiao(y,x);
    }
    dfs1(1,0);
    for(int i=1,x,y;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        int lca=get_lca(x,y);
        cha[x]++;cha[y]++;cha[lca]-=2;
    }
    dfs2(1);
    int ans=0;
    for(int i=2;i<=n;i++)
    {
        if(cha[i]==0)
            ans+=m;
        if(cha[i]==1) ans++;
    }
    cout<<ans;
}
View Code

おすすめ

転載: www.cnblogs.com/betablewaloot/p/12173663.html