「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;
}

posted @ 2018-12-18 19:55  h^ovny  阅读(104)  评论(0编辑  收藏  举报