おしゃべり
この質問への最小カットを研究するために、実際に見つかった木があった場合に問題に解決策を見るためには、\(DP \) 結局のところ、真剣に考えてどのように質問していませんでした完成最小カットした後、簡単に木に作られた\(DP \) 、そして感じZhenshuang後にああ〜
フェイス質問
溶液
解法一:最小割最大流
要件は、すべてのリーフノードがルートに達することができない、とあなたはエッジを削除することができるということですので、最小限のコストが最小カットのようにずっと見て、枠消しのために必要。しかし、よく見ると後の刈りリーフノードが行う方法を、多くのポイントを設定することがわかりましたか?
私達はちょうど、すべてのノードのルート、およびフロー側に接続されたすべてがされている、スーパー仮想ミーティングポイントを必要とする(INF \)を\します。(これらの人々のプラス側は、我々は確かにカットした側を選択することができないということなので)
すべての側面が刈りときに我々は、それを見ることができます。この時間は、この図は、2つの互いに素ポイントセットに実際にある、と\(S \)と\(T \)側にそれぞれ。これは最小に切断テンプレートとなり、最大流量を直接(最小、最大流量、明確な自己百度に数値的に等しいカット)を実行します。
対処方法2:ツリー\(DP \)
ルートにリーフノードは、私たちは木を検討することはできませんので\(DP \)ボトムアップの統計からを。ロジック(霧は何ですか
検討(dp_u \)\で表される\(U \) :ルートノード、必要最小限のコスト、転写式\(dp_u = \ SUM \分(dp_i、dis_i)\) 。前記\(Iは\)の\(U \)の子ノード、\(DISは、\)を表し\を(私は\)する(U \)\距離。
理解:封じ込めるために\(私は\)彼らは、元の最小値を維持するために風雲慣行オフダイレクトサブツリーとカットを遮断するために必要なサブツリーのリーフノード、最低価格、のルート、およびのために\( u)は\)複数のサブツリーを持っているので、彼らはお互いの各独立を要求し、(異なるサブ木があります。
ときの注意を払う必要がある(U \)\サブノード\(私は\)ときリーフノード上の、\(dp_iを\)に設定する\(INF \)を使用すると、この時点の削除を確保することができるようにすることは、確かです\(dis_i \) 。
コード
解決策1:
#include<bits/stdc++.h>
#define del(a,i) memset(a,i,sizeof(a))
#define ll long long
#define inl inline
#define il inl void
#define it inl int
#define ill inl ll
#define re register
#define ri re int
#define rl re ll
#define mid ((l+r)>>1)
#define lowbit(x) (x&(-x))
#define INF 0x3f3f3f3f
using namespace std;
template<class T>il read(T &x){
int f=1;char k=getchar();x=0;
for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
for(;k>='0'&&k<='9';k=getchar()) x=(x<<3)+(x<<1)+k-'0';
x*=f;
}
template<class T>il print(T x){
if(x/10) print(x/10);
putchar(x%10+'0');
}
ll mul(ll a,ll b,ll mod){long double c=1.;return (a*b-(ll)(c*a*b/mod)*mod)%mod;}
it qpow(int x,int m,int mod){
int res=1,bas=x%mod;
while(m){
if(m&1) res=(res*bas)%mod;
bas=(bas*bas)%mod,m>>=1;
}
return res%mod;
}
const int MAXN = 1e5+5;
int n,s,t,u,v,d,cur[MAXN],head[MAXN],num_edge=-1,dis[MAXN];
struct Edge{
int next,to,w;
Edge(){}
Edge(int next,int to,int w):next(next),to(to),w(w){}
}edge[MAXN<<2];
il add_edge(int u,int v,int w){
edge[++num_edge]=Edge(head[u],v,w),head[u]=num_edge;
edge[++num_edge]=Edge(head[v],u,w),head[v]=num_edge;
}
il build(int u,int fa){
bool fla=0;
for(ri i=head[u];i!=-1;i=edge[i].next){
if(edge[i].to==fa) continue;
edge[i^1].w=0;
build(edge[i].to,u),fla=1;
}
if(!fla) add_edge(u,t,INF);
}
inl bool BFS(int s,int t){
del(dis,0),dis[s]=1;
queue<int> q;q.push(s);
while(!q.empty()){
ri pos=q.front();q.pop();
for(ri i=head[pos];i!=-1;i=edge[i].next)
if(!dis[edge[i].to]&&edge[i].w>0){
dis[edge[i].to]=dis[pos]+1;
if(edge[i].to==t) return true;
q.push(edge[i].to);
}
}
return false;
}
it DFS(int now,int t,int flow){
if(now==t) return flow;
ri s=0,k;
for(ri &i=cur[now];i!=-1;i=edge[i].next)
if(dis[edge[i].to]==dis[now]+1&&edge[i].w>0){
k=DFS(edge[i].to,t,min(flow-s,edge[i].w));
s+=k,edge[i].w-=k,edge[i^1].w+=k;
if(s==flow) break;
}
if(s==0) dis[now]=0;
return s;
}
it Dinic(int s,int t){
ri res=0;
while(BFS(s,t)){
memcpy(cur,head,sizeof(head));
res+=DFS(s,t,INF);
}
return res;
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
read(n),read(s),t=n+1,del(head,-1);
for(ri i=1;i<n;++i) read(u),read(v),read(d),add_edge(u,v,d);
build(s,0);
printf("%d",Dinic(s,t));
return 0;
}
対処方法2:
#include<bits/stdc++.h>
#define del(a,i) memset(a,i,sizeof(a))
#define ll long long
#define inl inline
#define il inl void
#define it inl int
#define ill inl ll
#define re register
#define ri re int
#define rl re ll
#define mid ((l+r)>>1)
#define lowbit(x) (x&(-x))
#define INF 0x3f3f3f3f
using namespace std;
template<class T>il read(T &x){
int f=1;char k=getchar();x=0;
for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
for(;k>='0'&&k<='9';k=getchar()) x=(x<<3)+(x<<1)+k-'0';
x*=f;
}
template<class T>il print(T x){
if(x/10) print(x/10);
putchar(x%10+'0');
}
ll mul(ll a,ll b,ll mod){long double c=1.;return (a*b-(ll)(c*a*b/mod)*mod)%mod;}
it qpow(int x,int m,int mod){
int res=1,bas=x%mod;
while(m){
if(m&1) res=(res*bas)%mod;
bas=(bas*bas)%mod,m>>=1;
}
return res%mod;
}
const int MAXN = 1e5+5;
int n,s,dp[MAXN],u,v,d,head[MAXN],num_edge;
struct Edge{
int next,to,dis;
Edge(){}
Edge(int next,int to,int dis):next(next),to(to),dis(dis){}
}edge[MAXN<<1];
il add_edge(int u,int v,int dis){
edge[++num_edge]=Edge(head[u],v,dis),head[u]=num_edge;
edge[++num_edge]=Edge(head[v],u,dis),head[v]=num_edge;
}
il DFS(int u,int fa){
bool fla=0;
for(ri i=head[u];i;i=edge[i].next){
if(edge[i].to==fa) continue;fla=1;
DFS(edge[i].to,u),dp[u]+=min(dp[edge[i].to],edge[i].dis);
}
if(!fla) dp[u]=INF;
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
read(n),read(s);
for(ri i=1;i<n;++i) read(u),read(v),read(d),add_edge(u,v,d);
DFS(s,0);
printf("%d",dp[s]);
return 0;
}
概要
最小カットも重要な支店網の流れであるが、また、ゲームのビューを構築するために、多くの質問、気持ちを見つけ、自分自身をマスターすることができるようにさまざまなスキルを習得します。