P2986 [USACO10MAR] Gran reunión de vacas G (换 根 dp)

Portal de temas

Esta pregunta es una extensión de esta pregunta .

Pregunta: Hay un árbol, puede elegir un nodo raíz, el costo de este nodo raíz es ∑ c [i] ∗ dis [i] \ sum c [i] * dis [i]c [ i ]d i s [ i ]c [i] c [i]c [ i ] representa el peso en puntos del punto i,dis [i] dis [i]d i s [ i ] representa la distancia desde el punto i hasta el nodo raíz.

Idea: Primero trate con el costo al tomar 1 como nodo raíz, y luego atraviese el árbol y transfiera de acuerdo con la ecuación.

  • f [a] = f [x] - tamaño [i] ∗ dis (x, a) + (totc [i] - tamaño [i]) ∗ dis (x, a) f [a] = f [x] - tamaño [i] * dis (x, to) + (tot_ {c [i]} - tamaño [i]) * dis (x, to) f [ t o ]=f [ x ]-s i z [ i ]d i s ( x ,t o )+( t o tc [ i ]-s i z [ i ] )d i s ( x ,t o )

tu [i] tu [i] s i z [ i ] representa la suma de c [i] en el subárbol i.

Código:

#include<bits/stdc++.h>
#define endl '\n'
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define pii pair<int,int>
#define sz(x) (int)(x).size()
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read()
{
    
    
    int x=0,f=1;
    char ch=gc();
    while(ch<'0'||ch>'9')
    {
    
    
        if(ch=='-')
            f=-1;
        ch=gc();
    }
    while(ch>='0'&&ch<='9')
    {
    
    
        x=x*10+ch-'0';
        ch=gc();
    }
    return x*f;
}
using namespace std;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const double eps=1e-7;

vector<pii>e[N];
int siz[N],f[N],n,c[N],m=0;
void dfs1(int fa,int x,int dis)
{
    
    
    siz[x] = c[x];
    for(auto i:e[x])
    {
    
    
        if(i.first==fa)
            continue;
        dfs1(x,i.first,dis+i.second);
        siz[x]+=siz[i.first];
    }
    f[1] = f[1] + c[x]*dis;
}
void dfs2(int fa,int x)
{
    
    
    for(auto i:e[x])
    {
    
    
        if(i.first==fa)
            continue;
        int to = i.first;
        f[to] = f[x]-siz[to]*i.second+(m-siz[to])*i.second;
        dfs2(x,to);
    }
}
void solve()
{
    
    
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>c[i],m+=c[i];
    for(int i=1;i<n;i++)
    {
    
    
        int u,v,w;
        cin>>u>>v>>w;
        e[u].pb(mp(v,w));
        e[v].pb(mp(u,w));
    }
    dfs1(1,1,0);
    dfs2(1,1);
    cout<<*min_element(f+1,f+n+1)<<endl;
}

signed main()
{
    
    
    solve();

    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/Joker_He/article/details/113056481
Recomendado
Clasificación