ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Hamiltonian Spanning Tree - CodeForces - 618D 【DFS 贪心】

2020-05-07 09:01:20  阅读:300  来源: 互联网

标签:618D Hamiltonian int Tree tot leq dfs printf lld


题目链接

CF618D

题意

n个点,任意两点之间有一条无向边,每条边的权值都是y,现在给你一个生成树,这个生成树上的权值从y改成了x。问你现在遍历所有的点一次且仅一次的代价和最小是多少?
\((2\leq n \leq 200 000, 1\leq x,y \leq 10^9)\)

思路

  • 不是很懂,好像在找规律
  • 如果y<x: 那么选在生成树上的边越少越好。
    • 一般情况下,可以选到个完全没有用生成树上的边的路径,\(y*(n-1)\);
    • 极端情况,有一个点连着剩下n-1个点,即有一个点的度数为n-1,那么一定要选到一条在生成树上的边,\(x+y*(n-2)\)。
  • 如果x<=y:那么选的边在生成树上越多越好。
    • 我一开始以为是求树的直径,然后并不是 ex:1->2,3->2,2->4,4->5,4->6
    • 每个点只经过一次:度数最多为2.
    • a->b这条边能不能选:看b有没有把两个度数用掉。所以用dfs。

代码

#include<bits/stdc++.h>
#define DEBUG1
using namespace std;
typedef long long ll;
const int MAXN=200005;
struct Edge{
	int to,next;
}edge[MAXN<<1];
int head[MAXN],deg[MAXN];
int cnt,len;
ll ans,n,x,y;
void add_edge(int u,int v){
	edge[++cnt].to=v;
	edge[cnt].next=head[u];
	head[u]=cnt;
	edge[++cnt].to=u;
	edge[cnt].next=head[v]; 
	head[v]=cnt;
}
int tmp=0;
bool dfs(int u,int fa){
	#ifdef DEBUG
	tmp++;
	if(tmp>=20) return false;
	#endif
	int tot=2;
	for(int i=head[u];i;i=edge[i].next){
		int to = edge[i].to;
		#ifdef DEBUG
			printf("u:%d,fa:%d,to:%d,tot:%d\n",u,fa,to,tot);
		#endif
		if(to==fa) continue;
		//dfs(to,v):如果这个为false则表明子节点已经用掉了2条边了
		//tot:如果tot==0,那么说明这个点已经用掉2条边了 		
		// 这两种情况下,这一条边都不能用了
		if(dfs(to,u)&&tot){
			len++;
			tot--;
		}
	}
	return tot;
}
int main()
{
	scanf("%lld%lld%lld",&n,&x,&y);
	int u,v;
	bool flag=false;
	for(ll i=1;i<n;i++){
		scanf("%d%d",&u,&v);
		add_edge(u,v);
		deg[u]++;
		deg[v]++;
		if(deg[u]==n-1||deg[v]==n-1)flag=true;
	}
	if(x>=y){
		if(flag) printf("%lld\n",y*(n-2)+x);
		else printf("%lld\n",y*(n-1));
		return 0;
	}
	else{
		dfs(1,0);
		ans=len*x+(n-1-len)*y;
		printf("%lld\n",ans);
	}
	return 0;
} 

标签:618D,Hamiltonian,int,Tree,tot,leq,dfs,printf,lld
来源: https://www.cnblogs.com/xuwanwei/p/12837850.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有