HDU 4582 DFS spanning tree
时间:2020-03-07
本文章向大家介绍HDU 4582 DFS spanning tree,主要包括HDU 4582 DFS spanning tree使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题意:
一张无向图中告诉你一个dfs树,还有若干反向边。问你如何选取最小的边使得所有只包含一条反向边的环被覆盖。
转化题意,一条不在生成树上的边能构成一个环,假设这条边是 \(u-v\) ,那么就可以看作在dfs生成树上的一条 \(u-v\) 的路径。要求在生成树上选最少的边使得能让每一条路径内都至少有一条选的边
这题有个特点,题目说了这些非树边都是反向边,那就说明了 \(u,v\) 的 lca 一定是 \(u,v\) 中的一个
我们这边设 \(u\) 的深度比 \(v\) 的深度小
很像线段覆盖问题,还记得我们线段覆盖怎么做的么,按照右端点排序,然后如果一条线段实在要放就一定要放在最边上
这题也类似,按照第一关键字 \(u\) 第二关键字 \(v\) 按照深度从深到浅排,
然后暴力模拟,如果从 \(v\) 开始一直往 \(u\) 暴力跳,如果路上的边都没被标记过,那么就肯定要选一个了,选 \(u\) 往 \(v\) 方向儿子的那条边,因为枚举顺序就是从深到浅,更深的路径已经被处理过了,所以要尽量放的浅一点
我的代码里标记路径是 \(vis[u]\) 表示 \(u\) 节点往父亲方向的边是否被标记
注意常数,交之前洗把脸
// This code writed by chtholly_micromaker(MicroMaker)
#include <bits/stdc++.h>
#define reg register
using namespace std;
const int MaxN=2050;
struct Edge
{
int nxt,to;
}E[MaxN<<2];
int dep[MaxN];
struct Path
{
int l,r;
inline bool operator < (const Path &nt) const
{
if(dep[l]==dep[nt.l])
return dep[r]>dep[nt.r];
return dep[l]>dep[nt.l];
}
}pt[20050];
bool vis[MaxN];
int father[MaxN];
template <class t> inline void read(t &s)
{
s=0;
reg int f=1;
reg char c=getchar();
while(!isdigit(c))
{
if(c=='-')
f=-1;
c=getchar();
}
while(isdigit(c))
s=(s<<3)+(s<<1)+(c^48),c=getchar();
s*=f;
return;
}
int hd[MaxN],en,n,m;
inline void adde(int u,int v)
{
++en;
E[en]=(Edge){hd[u],v};
hd[u]=en;
return;
}
inline void dfs(int u,int fa)
{
father[u]=fa;
for(int i=hd[u];~i;i=E[i].nxt)
{
reg int v=E[i].to;
if(v==fa)
continue;
dep[v]=dep[u]+1;
dfs(v,u);
}
return;
}
inline void work()
{
memset(hd,-1,sizeof hd);en=0;
memset(vis,false,sizeof vis);
reg int u,v;
for(int i=1;i<n;++i)
{
read(u);read(v);
adde(u,v);
adde(v,u);
}
dep[1]=1;dfs(1,0);
m-=n-1;
for(int i=1;i<=m;++i)
{
read(pt[i].l);read(pt[i].r);
if(dep[pt[i].l]>dep[pt[i].r])
swap(pt[i].l,pt[i].r);
}
sort(pt+1,pt+m+1);
reg int ans=0;
for(int i=1;i<=m;++i)
{
reg int pos=pt[i].r;
while(father[pos]!=pt[i].l)
{
if(vis[pos])
break;
pos=father[pos];
}
if(!vis[pos])
{
vis[pos]=true;
++ans;
}
}
printf("%d\n",ans);
return;
}
signed main(void)
{
while(cin>>n>>m&&n&&m)
work();
return 0;
}
原文地址:https://www.cnblogs.com/chinesepikaync/p/12436781.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 200行Python代码实现贪吃蛇
- 简单说维特比算法 - python实现
- Android绘图及Bitmap几个知识点整理
- Spark Pipeline官方文档
- Python-时间及日期-07-获取本周或上周几具体日期
- Spark Job-Stage-Task实例理解
- 想查看微信好友撤回的消息?Python帮你搞定
- MySQL 案例:同步中断与SQL线程类型转换
- Android端Charles抓包
- Spring boot 启动提示数据源错误
- leetcode树之从上到下打印二叉树
- 整理C/C++的可变参数
- ThingJS结合Web地图API开发,让数据展示更加出色!
- 如何分析交易记录?
- [技术创作101训练营]小程序云开发实战:从零搭建科技爱好者周刊小程序