ハーフ答え、貪欲
(LCAは、彼はそれをしないだろうことを見つけるために、ボードを終えました)
フォーム:
最大の最小化
、最大値の最小化
そのような事は、すべての可能性に半分の答えです。
このシナリオでは、現在のトラックの半分を持って最短できます\(L \) 。我々は、最短の長さに、チェックする\(L \) 、制限の下できない未満のM個のトラック構造。あなたはさせることができた場合は(L \)\それが少し大きく、そうでない場合。
だから今検討し、現在のトラックに最短できました\(L \)トラックの下に、いくつかの制限のために開くことができます。
定義される:\(F [U] \)である\(U \)ノード方向の親ノードに貢献するトラックの最大長。\(CNTは\)に構成されている現在のトラックの数、初期値である\(0 \) 。(\ W(u、v)は )\ 表す\(U \)に\(V \)経路長を。
我々マップ、形状の部分図を得る:「ほうき」ほうきの柄である(U \)\親ノードに\(FA \)パス、ほうきの各々は、発現されるべき\(U \)に子ノード\(V_I \)経路、小ごみの上面に接着されるほうきの各\(V_I \) 。私たちは、現在の状況では、すべてのことを想定(F [V_I] \)は\算出されています。
私たちは、最初に従ってほうきもの(F [V_I] +(W U、V_I)\)\ 昇順、これらのほうきを考慮しなければならない(\ ^ *)\ ;
- ルートほうきの必要な長さあれば\(W(U、V_I) \) 最大の貢献に加え、子ノード\(F [V_I]が\)以上有している\(L \) 、およびそのショーは、我々は、正当に取得することそれは追跡し、
cnt++
これはほうきほうきから抜かなければなりません。 - 最短フラナガンほうきほうきそれ2本のほうきはただのようになりながら、別の対象を見つけることができなければならない現在の場合(Lが\)\右に等しいだけ大きなまたは\(L \) 、これら2つは、ほうきを引っ張っている必要があります我々は合法的なトラックを取得しますので
cnt++
。ここではちょうど、後者缶以外の組み合わせで存在するかまたは両方の長さと等しくないことが、厳密に現在の状態のちょうど、すなわち、組み合わせであることに留意されたい\(Lは\)現在小の組み合わせた長さを超えます。 - 現在のほうきが短すぎるようにした場合、その上の2つの条件が満たされていないこと、そしてこれが新しいトラックを取得するために結合されている多くの親パスを保つことがほうきのルート、および缶賞であると考えてすべてのパスは一度だけ使用することができるのでほうきは、ユニークです。その後、状態遷移方程式を挙げることができる:
\ [F [U] = MAX(F [V_I] + W(U、V_I))、息子で\クワッドV_I \(U)\]
フルを検討するようなほうき。
さて、私たち、全体像を考える\(DFSが\)リーフノードの初期値がクリアされている:彼らのほうき、境界条件を考慮すること\(F [リーフ] = 0 \) 。
その後、我々は知ることができ、CNTとMの関係の大きさを比較する(L \)\値を調整すべきかの。
それはまだ終わっていません。するこれらのほうきを考えてみましょう\(^ * \)ステップは、我々が使用するための質問を伴うことmultiset
、我々はいくつかの素敵得たような最適化を、\(ログを\) 。
破壊の指を壊すの複雑さがあると推定さ......数えないことが判明(O(N \ログ^ \ \)2 N) について?
コード:
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
char c=getchar();int x=0;
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())
x=x*10+c-'0';
return x;
}
const int N=50005,INF=0x3f3f3f3f;
int n,m,cnt,curl;
int f[N];
struct node
{
int v,w;
node(){}
node(int to,int weight)
{
v=to;
w=weight;
}
};
vector<node> G[N];
void dfs(int u,int fa)
{
multiset<int> S;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i].v,w=G[u][i].w;
if(v!=fa)
{
dfs(v,u);
if(f[v]+w>=curl)cnt++;
else S.insert(f[v]+w);
}
}
while(!S.empty())
{
multiset<int>::iterator it_cur=S.begin();
S.erase(it_cur);
multiset<int>::iterator it=S.lower_bound(curl-*it_cur);
if(it!=S.end())cnt++,S.erase(it);
else f[u]=max(f[u],*it_cur);
}
}
inline bool chk(int x)
{
memset(f,0,sizeof(f));
cnt=0;
curl=x;
dfs(1,0);
if(cnt>=m)return 1;
else return 0;
}
int main()
{
cin>>n>>m;
for(int i=1;i<n;i++)
{
int u=read();
int v=read();
int w=read();
G[u].push_back(node(v,w));
G[v].push_back(node(u,w));
}
int l=0,r=INF,mid,ans=0;
while(l<=r)
{
mid=((l+r)>>1);
if(chk(mid))
{
ans=mid;
l=mid+1;
}
else r=mid-1;
}
cout<<ans;
return 0;
}
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
char c=getchar();int x=0;
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())
x=x*10+c-'0';
return x;
}
const int N=50005,INF=0x3f3f3f3f;
int n,m,cnt,curl;
int f[N];
struct node
{
int v,w;
node(){}
node(int to,int weight)
{
v=to;
w=weight;
}
};
vector<node> G[N];
void dfs(int u,int fa)
{
multiset<int> S;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i].v,w=G[u][i].w;
if(v!=fa)
{
dfs(v,u);
if(f[v]+w>=curl)cnt++;
else S.insert(f[v]+w);
}
}
while(!S.empty())
{
multiset<int>::iterator it_cur=S.begin();
S.erase(it_cur);
multiset<int>::iterator it=S.lower_bound(curl-*it_cur);
if(it!=S.end())cnt++,S.erase(it);
else f[u]=max(f[u],*it_cur);
}
}
inline bool chk(int x)
{
memset(f,0,sizeof(f));
cnt=0;
curl=x;
dfs(1,0);
if(cnt>=m)return 1;
else return 0;
}
int main()
{
cin>>n>>m;
for(int i=1;i<n;i++)
{
int u=read();
int v=read();
int w=read();
G[u].push_back(node(v,w));
G[v].push_back(node(u,w));
}
int l=0,r=INF,mid,ans=0;
while(l<=r)
{
mid=((l+r)>>1);
if(chk(mid))
{
ans=mid;
l=mid+1;
}
else r=mid-1;
}
cout<<ans;
return 0;
}
------------最後の内容を復元------------
LGOJトラック建てP5021
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
char c=getchar();int x=0;
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())
x=x*10+c-'0';
return x;
}
const int N=50005,INF=0x3f3f3f3f;
int n,m,cnt,curl;
int f[N];
struct node
{
int v,w;
node(){}
node(int to,int weight)
{
v=to;
w=weight;
}
};
vector<node> G[N];
void dfs(int u,int fa)
{
multiset<int> S;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i].v,w=G[u][i].w;
if(v!=fa)
{
dfs(v,u);
if(f[v]+w>=curl)cnt++;
else S.insert(f[v]+w);
}
}
while(!S.empty())
{
multiset<int>::iterator it_cur=S.begin();
S.erase(it_cur);
multiset<int>::iterator it=S.lower_bound(curl-*it_cur);
if(it!=S.end())cnt++,S.erase(it);
else f[u]=max(f[u],*it_cur);
}
}
inline bool chk(int x)
{
memset(f,0,sizeof(f));
cnt=0;
curl=x;
dfs(1,0);
if(cnt>=m)return 1;
else return 0;
}
int main()
{
cin>>n>>m;
for(int i=1;i<n;i++)
{
int u=read();
int v=read();
int w=read();
G[u].push_back(node(v,w));
G[v].push_back(node(u,w));
}
int l=0,r=INF,mid,ans=0;
while(l<=r)
{
mid=((l+r)>>1);
if(chk(mid))
{
ans=mid;
l=mid+1;
}
else r=mid-1;
}
cout<<ans;
return 0;
}