原题链接:

https://ac.nowcoder.com/acm/problem/22598

题目大意:

Rinne 最近了解了如何快速维护可支持插入边删除边的图,并且高效的回答一下奇妙的询问。她现在拿到了一个 个节点 条边的无向连通图,每条边有一个边权
现在她想玩一个游戏:选取一个 “重要点” S,然后选择性删除一些边,使得原图中所有除 S 之外度为 1 的点都不能到达 S。
定义删除一条边的代价为这条边的边权,现在 Rinne 想知道完成这个游戏的最小的代价,这样她就能轻松到达 rk1 了!作为回报,她会让你的排名上升一定的数量。

解题思路:

树形记录删除节点i下面的一些边使叶子节点到不了根节点的最小权值。递推公式为:

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pi;
typedef complex <double> cp;
#define debug(a) cout<<#a<<":"<<a<<endl;
#define fr freopen("in.txt","r",stdin);
#define Fill(x,a) memset(x,a,sizeof(x))
#define cpy(a,b) memcpy(a,b,sizeof(a))
const double PI = acos(-1);
const ll INF=0x3f3f3f3f;
const ll N=1e6+7;
const ll mod=1e9+7;
ll maxn,minn;
ll T,n,m,q,s;

ll dp[N];
ll head[N];
ll cnt;
struct aa{
    ll u,w,next;
}edge[N];

void init(){
    cnt=1;
    Fill(dp,0);
    Fill(head,0);
    return ;
}

void add(ll u,ll v,ll w){
    edge[cnt].u=v;
    edge[cnt].w=w;
    edge[cnt].next=head[u];
    head[u]=cnt++;
    return ;
}

void dfs(ll u,ll p){
    ll v,w;
    ll a=0;
    if(edge[head[u]].next==0&&u!=s){
        dp[u]=INF;
        return ;
    }
    for(ll i=head[u];i!=0;i=edge[i].next){
        v=edge[i].u;
        w=edge[i].w;
        if(v==p)    continue;
        dfs(v,u);
        dp[u]=dp[u]+min(dp[v],w);
    }
    return ;
}

int main(){
    ll u,w,v;
    init();
    cin>>n>>m>>s;
    for(ll i=1;i<=m;i++){
        scanf("%lld%lld%lld",&u,&v,&w);
        add(u,v,w);
        add(v,u,w);
    }

    dfs(s,0);
    cout<<dp[s]<<endl;

    return 0;
}