链接: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;
}