hdu4912 Paths on the tree --- LCA贪心

2024-05-28 10:48
文章标签 贪心 tree lca paths hdu4912

本文主要是介绍hdu4912 Paths on the tree --- LCA贪心,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

给一棵n个结点的树,m条路径的起点和终点,

问至多可以选择多少条路径使其两两间没有公共点。


这题的主要问题是,

1、如何判断两条路径上没有交点

2、按什么策略来选

看上去感觉是最大匹配问题,但nm的范围较大问题1无法高效的解决。

画个图发现可能和LCA有关,但比赛时不知道这到底有什么用,完全没想贪心。

要选择尽量多,就是要尽量避免冲突。

我们选择一个点作为根,把给的边画出来建树就可以发现,尽量选深度大的路径可以使冲突尽量小。

于是把路径按LCA深度由大到小排序,依次和之前不冲突就可以选。

下面就是判断两条路径上有没有交点,

当一条路径选了之后,以其LCA的子树上的点为起点或终点的路径一定与其有交点。


#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f
#pragma comment(linker, "/STACK:16777216")
#define eps 1e-6
#define ll long long
using namespace std;const int maxn=1e5+10;
int dep[maxn];
struct node
{int v,id;node* next;
}ed[maxn<<2],*head[maxn],*q[maxn];struct qnode
{int u,v,ans;//存询问结点,ans最近公共祖先
} qu[maxn];bool cmp(const qnode &a,const qnode &b)
{return dep[a.ans]>dep[b.ans];
}int fa[maxn],vis[maxn],cnt;void init(int n)
{cnt=0;memset(vis,0,sizeof vis);memset(head,0,sizeof head);memset(q,0,sizeof q);for(int i=0;i<=n;i++)fa[i]=i;
}int getfa(int x)
{if(fa[x]==x) return x;return fa[x]=getfa(fa[x]);
}void tarjan(int u)
{fa[u]=u,vis[u]=1;for(node *p=q[u];p!=NULL;p=p->next){if(vis[p->v]){int id=p->id;qu[id].ans=getfa(p->v);}}for(node *p=head[u];p!=NULL;p=p->next){if(!vis[p->v]){tarjan(p->v);fa[p->v]=u;}}
}void adde(node *e[],int u,int v,int id)
{ed[cnt].v=v;ed[cnt].id=id;ed[cnt].next=e[u];e[u]=&ed[cnt++];
}void dfs(int u)
{for(node *p=head[u];p!=NULL;p=p->next){if(dep[p->v]>dep[u]&&!vis[p->v]){vis[p->v]=1;dfs(p->v);}}
}void dfss(int u,int d)
{for(node *p=head[u];p!=NULL;p=p->next){if(!vis[p->v]){vis[p->v]=1;dep[p->v]=d;dfss(p->v,d+1);}}
}int main()
{int n,m,i,a,b;while(~scanf("%d%d",&n,&m)){init(n);for(i=0;i<n-1;i++){scanf("%d%d",&a,&b);adde(head,a,b,i);adde(head,b,a,i);}for(i=0;i<m;i++){scanf("%d%d",&a,&b);qu[i].u=a;qu[i].v=b;adde(q,a,b,i);adde(q,b,a,i);}memset(vis,0,sizeof vis);dep[1]=0;vis[1]=1;dfss(1,1);//预处理 标号-深度memset(vis,0,sizeof vis);tarjan(1);//以1为根找lcaint ans=0;sort(qu,qu+m,cmp);memset(vis,0,sizeof vis);for(i=0;i<m;i++){//printf("s:%d t:%d p:%d dep:%d\n",qu[i].u,qu[i].v,qu[i].ans,dep[qu[i].ans]);if(!vis[qu[i].u]&&!vis[qu[i].v]&&!vis[qu[i].ans]){ans++;vis[qu[i].ans]=1;dfs(qu[i].ans);//标记子树}}printf("%d\n",ans);}return 0;
}


这篇关于hdu4912 Paths on the tree --- LCA贪心的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1010356

相关文章

poj1330(LCA最近公共祖先)

题意:求最近公共祖先 思路:之前学习了树链剖分,然后我就用树链剖分的一小部分知识就可以解这个题目了,记录每个结点的fa和depth。然后查找时,每次将depth大的结点往上走直到x = y。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring>

usaco 1.3 Barn Repair(贪心)

思路:用上M块木板时有 M-1 个间隙。目标是让总间隙最大。将相邻两个有牛的牛棚之间间隔的牛棚数排序,选取最大的M-1个作为间隙,其余地方用木板盖住。 做法: 1.若,板(M) 的数目大于或等于 牛棚中有牛的数目(C),则 目测 给每个牛牛发一个板就为最小的需求~ 2.否则,先对 牛牛们的门牌号排序,然后 用一个数组 blank[ ] 记录两门牌号之间的距离,然后 用数组 an

poj 3190 优先队列+贪心

题意: 有n头牛,分别给他们挤奶的时间。 然后每头牛挤奶的时候都要在一个stall里面,并且每个stall每次只能占用一头牛。 问最少需要多少个stall,并输出每头牛所在的stall。 e.g 样例: INPUT: 51 102 43 65 84 7 OUTPUT: 412324 HINT: Explanation of the s

poj 2976 分数规划二分贪心(部分对总体的贡献度) poj 3111

poj 2976: 题意: 在n场考试中,每场考试共有b题,答对的题目有a题。 允许去掉k场考试,求能达到的最高正确率是多少。 解析: 假设已知准确率为x,则每场考试对于准确率的贡献值为: a - b * x,将贡献值大的排序排在前面舍弃掉后k个。 然后二分x就行了。 代码: #include <iostream>#include <cstdio>#incl

POJ2010 贪心优先队列

c头牛,需要选n头(奇数);学校总共有f的资金, 每头牛分数score和学费cost,问合法招生方案中,中间分数(即排名第(n+1)/2)最高的是多少。 n头牛按照先score后cost从小到大排序; 枚举中间score的牛,  预处理左边与右边的最小花费和。 预处理直接优先队列贪心 public class Main {public static voi

ural 1820. Ural Steaks 贪心

1820. Ural Steaks Time limit: 0.5 second Memory limit: 64 MB After the personal contest, happy but hungry programmers dropped into the restaurant “Ural Steaks” and ordered  n specialty steaks

ural 1014. Product of Digits贪心

1014. Product of Digits Time limit: 1.0 second Memory limit: 64 MB Your task is to find the minimal positive integer number  Q so that the product of digits of  Q is exactly equal to  N. Inpu

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

树(Tree)——《啊哈!算法》

树 什么是树?树是一种特殊的图,不包含回路的连通无向树。 正因为树有着“不包含回路”这个特点,所以树就被赋予了很多特性。 一棵树中的任意两个结点有且仅有唯一的一条路径连通。一棵树如果有n个结点,那么它一定恰好有n-1条边。在一棵树中加一条边将会构成一个回路。 一棵树有且只有一个根结点。 没有父结点的结点称为根结点(祖先)。没有子结点的结点称为叶结点。如果一个结点既不是根结点也不是叶

226 Invert Binary Tree

//226 Invert Binary Tree//算法思路:主要使用递归算法public class Solution {public TreeNode invertTree(TreeNode root) {//1 出口 空节点if (root==null)return null;//2 递归 调用自己TreeNode left = root.left;TreeNode right = ro