正题

题目链接:https://www.luogu.com.cn/problem/AT3968


题目大意

给出nnn个点的一棵树,然后给出mmm条路径。每条边的权值是它是否又被正向经过+是否又被反向经过,给每条路径定向使得所有边的权值和最大。输出方案。

1≤n,m≤20001\leq n,m\leq 20001≤n,m≤2000


解题思路

显然第一条路径我们可以随意定向,然后与它同向的且经过重复边的路径我们取反其中一条然后再以这条路径继续去取反别的相交路径。
这样下去会发现显然两条路径相交的部分都会被统计两次,也就是如果一条边被经过了两次那么这里的贡献就是222,否则被经过一次就是111,也就是答案能到达上界。

但是这样构造显然容易出问题,考虑一个更加系统的构造方法。

先把所有路径挂到两端点上,然后我们每次找到一个叶子节点,考虑这个叶子节点

  • 没有路径:那么直接删除这个叶子。
  • 有一条路径:那么这条路径的方向和这个叶子无关,直接把路径丢到父节点然后删除这个叶子。
  • 有两条或者以上路径:此时我们指定任意两条边反向,但是这两条边谁正谁反还未确定,假设是(x,a),(x,b)(x,a),(x,b)(x,a),(x,b),那我们新建一条路径(a,b)(a,b)(a,b)(也就是这两条路径在分叉点后产生的新路径)然后这两条再根据这条路径确定方向。

用setsetset维护端点的路径,删掉的路径记得在对应的节点也删掉,细节有点多慢慢调。

时间复杂度:O(n2log⁡n)O(n^2\log n)O(n2logn)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<queue>
#define mp(x,y) make_pair(x,y)
using namespace std;
const int N=2100,M=5100;
struct node{int to,next;
}a[N<<1];
int n,m,tot,c[N],ls[N],in[N],fa[N];
int ps[N],pt[N],s[M],t[M];
queue<int> q;set<int> p[M];
pair<int,int> ans[M];
void addl(int x,int y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return;
}
void dfs(int x){for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa[x])continue;fa[y]=x;dfs(y);in[x]++;}return;
}
bool work(int x,int z,int fr){if(x==z)return 1;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fr)continue;int w=work(y,z,x);if(w){if(y==fa[x])c[x]++;else c[y]++;return 1;}}return 0;
}
void given(int x){int i=*p[x].begin();p[x].erase(i);p[fa[x]].insert(i);if(i>0)s[i]=fa[x];else t[-i]=fa[x];i=abs(i);if(s[i]==t[i]){p[s[i]].erase(i);p[s[i]].erase(-i);}return;
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);addl(x,y);addl(y,x);}tot=m;dfs(1);int sum=0;for(int i=1;i<=m;i++){scanf("%d%d",&s[i],&t[i]);ps[i]=s[i];pt[i]=t[i];p[s[i]].insert(i);p[t[i]].insert(-i);work(s[i],t[i],0);}for(int i=2;i<=n;i++){if(!in[i])q.push(i);sum+=min(c[i],2);}while(!q.empty()){int x=q.front();q.pop();if(x==1)break;in[fa[x]]--;if(!in[fa[x]])q.push(fa[x]);if(p[x].size()==1)given(x);else if(p[x].size()>1){++tot;int i=*p[x].begin();p[x].erase(i);int j=*p[x].begin();p[x].erase(j);s[tot]=(i>0)?t[i]:s[-i];t[tot]=(j>0)?t[j]:s[-j];if(s[tot]!=t[tot])p[s[tot]].insert(tot),p[t[tot]].insert(-tot);p[s[tot]].erase(-i);p[t[tot]].erase(-j);ans[abs(i)]=mp(tot,-i/abs(i));ans[abs(j)]=mp(tot, j/abs(j));while(!p[x].empty())given(x);}}printf("%d\n",sum);for(int i=tot;i>=1;i--){if(ans[i].second!=0)ans[i].first=ans[ans[i].first].first*ans[i].second;else ans[i].first=1;}for(int i=1;i<=m;i++){if(ans[i].first>0)printf("%d %d\n",ps[i],pt[i]);else printf("%d %d\n",pt[i],ps[i]);}return 0;
}

AT3968-[AGC025E] Walking on a Tree【构造】相关推荐

  1. Codeforces Round #453 (Div. 1) D. Weighting a Tree 构造 + dfs树

    传送门 文章目录 题意: 思路: 题意: 给你一颗nnn个点的图,每个点都有一个点权cic_ici​,要求你给每个边赋一个权值kik_iki​,要求对于每个点与他相连的边的权值之和等于这个点的点权ci ...

  2. HDU 5573 Binary Tree 构造

    Binary Tree 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5573 Description The Old Frog King lives ...

  3. Codeforces Round #319 (Div. 1) B. Invariance of Tree 构造

    B. Invariance of Tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/576/ ...

  4. AtCoder Regular Contest 063 E - Integers on a Tree 构造 + 二分图染色

    传送门 题意: 给你一颗nnn个点的树,初始的时候某些点有权值pip_ipi​,现在你需要给没给定的点赋一个权值,使得任意相邻点权值之差的绝对值等于111,若无解输出NoNoNo. 1≤n≤1e5,1 ...

  5. BKD tree构造过程

    1. 将所有的点数据,写在内存中.并统计其总数 2. 根据其总数和每个叶子结点最多点数据的数量, 得出叶子结点的数量 long countPerLeaf = pointCount = values.s ...

  6. 实验三Huffman编码与解码

    一.实验原理 Huffman编码实现的数据结构 Huffman编码为可变长编码,若各码字长度按照所对应符号出现概率的大小逆序排列,则其平均长度最小. 编码步骤: 1.将信源符号按照出现概率由大到小的顺 ...

  7. [总结]2019年9月 OI学习/刷题记录

    从现在开始记录一下每天的学习情况.主力LOJ? 2019/9/5 LibreOJ #2543. 「JXOI2018」排序问题 答案显然是\(\frac{(n+m)!}{Cnt_1!Cnt_2!\cdo ...

  8. unity 灯笼_如何创建将自己拼成文字的漂亮灯笼

    unity 灯笼 In this tutorial, we will go through how to create a group of festival lanterns that arrang ...

  9. Python 文件与目录操作方法总结

    Python 有很多内置的模块和函数可用于文件的操作处理,这些函数都分布在几个模块上:如 os , os.path , shutil 和 pathlib 等等.本文收集了许多您需要知道的函数,以便在 ...

最新文章

  1. 智能驾驶计算平台算力技术
  2. 三、Qt Creator登录对话框
  3. pca主成分分析结果解释_SKLEARN中的PCA(Principal Component Analysis)主成分分析法
  4. Exchange 2010与Exchange Online混合部署PART 5:配置边缘
  5. LeetCode 1405. 最长快乐字符串(贪心)
  6. SpringCloud工作笔记063---Java 手机验证码生成_存储到redis
  7. mac netbeans java_在macOS上不安装JDK的情况下安装Netbeans
  8. 新型冠状病毒数据抓取及整理详细流程
  9. 防止***根据PHP中的错误信息爆路径
  10. SpreadJS:一款类Excel开发工具,功能涵盖Excel的 95% 以上
  11. 第4章第16节:图表:使用三维饼图制作年度销售额图表 [PowerPoint精美幻灯片实战教程]
  12. MTK平台替换签名key方法
  13. “ ipconfig 不是内部或者外部命令,也不是可运行的程序”问题的解决
  14. “大白兔”迎来60岁生日 各类衍生品受青睐
  15. 阿里格灵深瞳计算机视觉岗实习面经
  16. MyBatis简单的增删改查
  17. 证书相关的玩意儿(SSL,X.509,PEM,DER,CRT,CER,KEY,CSR,P12)
  18. 2019 年值得学习的顶级 JavaScript 框架与主题
  19. Java中Music类是什么_高效的Java音乐播放类
  20. 2021-2027全球与中国便携式超声波探伤仪市场现状及未来发展趋势

热门文章

  1. selenium autoit java_Java+Selenium——AutoIt工具处理文件上传
  2. mysql 卸载插件_MySQL 插件安装或卸载(window validate_password 为例)
  3. _云计算学习路线图素材课件,Linux中软件安装的方式
  4. sequelize模型关联_关于Sequelize连接查询时inlude中model和association的区别详解
  5. mysql group by 范围_MySQL 按照范围/等级 进行Group By
  6. 创新视角下的复盘 | 2021/08/01-2021/09/30
  7. 『软件工程3』你应该知道的三种原型实现模型:抛弃式、演化式、增量式
  8. [C++11]智能指针简单介绍
  9. 科学家的假想-substr的妙用
  10. AcWing 756. 蛇形矩阵