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; }