「Luogu P3931」SAC E#1 - 一道难题 Tree 解题报告

原题面

我环顾四周,发现大佬们的写法都好高端!

比较差劲的我,只能交上一份DFS的题解

思路:

DFS(当然了,其他算法也行)

要想切断叶子节点根节点的连接

就是在叶子节点根节点之间砍掉一条边

这明显就很符合DFS的性质,一条路一直走下去,遇到分枝就分开走

于是我们DFS每一条路径,然后求答案

复杂度为O(n)

但是——还没完!

我们可以发现DFS有三种情况

1、该节点为叶子节点,此时只能删去连接它和父节点的边

2、该节点为枝节点,有父节点和子节点,需要选择性的删除

3、该节点为根节点,只有子节点,只能删去连接它和子节点的边

Code:

#include<bits/stdc++.h>
#define INF 0x7f7f7f7f
using namespace std;
struct node{
    int to,cost;
    int nxt;
    node(int a,int b):to(a),cost(b){    }
    node(){ }
}b[200010];
int n,t,r;
int head[100010];
int read()
{
    int s=0;
    char c=getchar();
    while(!isdigit(c))
        c=getchar();
    while(isdigit(c))
    {
        s=(s<<1)+(s<<3)+c-'0';
        c=getchar();
    }
    return s;
}
void add(int x,int y,int cost)//建边
{
    b[++t]=node(y,cost);
    b[t].nxt=head[x];
    head[x]=t;
    b[++t]=node(x,cost);
    b[t].nxt=head[y];
    head[y]=t;
    return;
}
int Get(int k,int in)
{
    int i;
    int res=0;
    for(i=head[k];i;i=b[i].nxt)
        if(i!=(in^1))//成对变换原理,异或值相同但方向相反的边为一组,避免重复
            res+=Get(b[i].to,i);
    if(!b[head[k]].nxt&&k!=r)//确定是叶子节点
        res=b[in].cost;
    else
        res=min(res,b[in].cost);//否则两种方法选其一
    return res;
}
int main()
{
    int i;
    int x,y,cost;
    n=read();r=read();
    t=1;//初始赋1,利于成对变换
    for(i=1;i<n;i++)
    {
        x=read();y=read();cost=read();
        add(x,y,cost);
    }
    b[0].cost=INF;//对于根节点的双重保险,防止出什么岔子,比如结果为0
    printf("%d",Get(r,0));
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hovny/p/10139338.html