(dfs)Rinne Loves Edges

链接:https://ac.nowcoder.com/acm/contest/370/F
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld

题目描述

Rinne  最近了解了如何快速维护可支持插入边删除边的图,并且高效的回答一下奇妙的询问。

她现在拿到了一个 n 个节点 m 条边的无向连通图,每条边有一个边权 wiwi

现在她想玩一个游戏:选取一个 “重要点” S,然后选择性删除一些边,使得原图中所有除 S 之外度为 1 的点都不能到达 S。

定义删除一条边的代价为这条边的边权,现在 Rinne 想知道完成这个游戏的最小的代价,这样她就能轻松到达 rk1 了!作为回报,她会让你的排名上升一定的数量。

 

输入描述:

第一行三个整数 N,M,S,意义如「题目描述」所述。

接下来 M 行,每行三个整数 u,v,w 代表点 u 到点 v 之间有一条长度为 w 的无向边。

输出描述:

一个整数表示答案。

示例1

输入

复制

4 3 1 
1 2 1 
1 3 1 
1 4 1

输出

复制

3

说明

需要使得点 2,3,4 不能到达点 1,显然只能删除所有的边,答案为 3

示例2

输入

复制

4 3 1 
1 2 3 
2 3 1 
3 4 2

输出

复制

1

说明

需要使得点 4 不能到达点 1,显然删除边 2↔32↔3是最优的。

备注:

2≤S≤N≤105,M=N−12≤S≤N≤105,M=N−1,保证答案在 C++ long long 范围内。

题解:通过dfs 迭代从叶子节点到根(S 为根),在此过程判断中间节点的dp值与边权值从而更新。

#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<bitset>
#include<iomanip>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define eps (1e-8)
#define MAX 0x3f3f3f3f
#define u_max 1844674407370955161
#define l_max 9223372036854775807
#define i_max 2147483647
#define re register
#define pushup() tree[rt]=max(tree[rt<<1],tree[rt<<1|1])
#define nth(k,n) nth_element(a,a+k,a+n);  // 将 第K大的放在k位
#define ko() for(int i=2;i<=n;i++) s=(s+k)%i // 约瑟夫
#define ok() v.erase(unique(v.begin(),v.end()),v.end()) // 排序,离散化
using namespace std;

inline int read(){
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' & c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}

typedef long long ll;
const double pi = atan(1.)*4.;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fLL;
const int M=63;
const int N=1e5+5;

struct fun{
    int x;
    ll w;
};

vector<fun>v[N];
ll dp[N];

void dfs(int cut,int per){   // cut 当前节点 ,per 当前节点的父亲节点
    int leap=0;
    for(int i=0;i<v[cut].size();i++){   //  判断是否为叶子节点
        int y=v[cut][i].x;
        if(y==per) continue;
        else{
            leap=1;
            break;
        }
    }
    if(leap) dp[cut]=0;            //  不是,dp值为0
    for(int i=0;i<v[cut].size();i++){
        int y=v[cut][i].x;
        if(y==per) continue;
        dfs(y,cut);
        dp[cut]+=min(dp[y],v[cut][i].w);  
    }
    return ;
}
int main(){
    int n,m,s;
    scanf("%d %d %d",&n,&m,&s);
    memset(dp,INF,sizeof(dp));
    while(m--){
        int u,g; ll w;
        scanf("%d%d%lld",&u,&g,&w);
        v[u].push_back({g,w});
        v[g].push_back({u,w});
    }
    dfs(s,0);
    printf("%lld\n",dp[s]);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值