Luogu P3931 SAC E # 1 - 문제 퍼즐 나무에 대한 해결책

꼬꼬댁

주문이 질문에 작은 상처를 공부하지만, 문제에 대한 해결책을 볼 수에서 연습에있는 나무가있을 때 \ (DP \) 결국, 생각하는 방법을 심각하게 의심하지 않았다완성 된 최소 절단 한 후, 쉽게 나무로 만든 \ (민주당 \) , 다음 느낌 Zhenshuang 후 아 ~

얼굴 질문

얼굴 질문

해결책

해법 한 : 최소 비율 최대 흐름

요구 사항은 모든 잎 노드가 루트에 도달 할 수없는, 당신은 가장자리를 삭제할 수 있기 때문에, 최소 비용은 최소 컷처럼 많이 찾고, 테두리 지우기 필요합니다. 그러나 자세히 살펴보면 이후 베어 낸 리프 노드 포인트를 많이 설정하는 것이 발견, 어떻게 할까?

우리는 슈퍼 가상 만남의 장소, 모든 노드의 루트에 연결된 모든 및 흐름 측면입니다 필요 \ (INF를 \) . (이 사람들 플러스 측면 때문에 우리가 확실히 어느 쪽 삭감을 선택할 수 없다는 것입니다)

우리가 볼 수있는이 시간은 모든 측면 베어 낸 경우,이 수치는 실질적으로 두 개의 분리 된 지점 세트이며, \ (S \)\ (T \) 측에 각각. 이것은 최소한으로 잘라 템플릿되고, 최대 유량은 직접 (최소 최대 흐름, 명확한 자기 바이두와 같은 수치의 절단) 실행합니다.

해결 방법 2 : 트리 \ (민주당 \)

루트에 리프 노드, 우리는 나무 고려할 수 없기 때문에 \ (DP \) 아래에서 위로 통계에서합니다.논리 (안개는 무엇인가

고려 (dp_u \) \ 로 표시 \ (U \) 때 루트 노드 필요한 최소의 비용으로, 전사 식 : \ (dp_u = \ SUM \ 분 (dp_i, dis_i) \) . 상기 식에서 \ (나는 \)\ (U \) 자식 노드, \ (DIS \) 대표 \ (나는 \) 하기 (U \) \ 거리.

이해 : 포함하기 위해 \ (내가 \) 가 원래의 최소 유지하기 위해 Fengyun 관행 떨어져 직접 하위 트리와 상처를 차단하는 데 필요한 하위 트리의 리프 노드, 최저 가격의 루트 및 위해 \ ( 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;
}

개요

최소 컷도 중요한 지점 네트워크 흐름이지만, 또한 자신을 마스터 할 수있는 다른 기술을 배우고, 게임, 더 많은 질문의보기를 구축 느낌을 찾을 수 있습니다.

추천

출처www.cnblogs.com/TheShadow/p/11375198.html