[AGC025E]Walking on a Tree
题意:有一棵树,你要按顺序在树上走$m$次,每次从$u_i$到$v_i$或从$v_i$到$u_i$,走完后,如果一条边被单向经过,那么它贡献$1$的价值,如果一条边被双向经过,那么它贡献$2$的价值,给出所有的$(u_i,v_i)$,你要安排每次走路的方向以最大化价值
设边$i$被经过的次数为$c_i$,容易看出答案的上界是$\sum\min(c_i,2)$,下面我们构造性地说明这个上界总可以被达到
如果$n=1$,树中没有边,接下来考虑$n\gt1$
任选一个叶子$u$,设$e$为连接它的唯一一边,$v$为$e$的另一端点
如果$c_e=0$,直接删掉$u$,这对答案没有影响
如果$c_e=1$,我们也可以删掉$u$,只不过经过$u$的那条路径的端点要缩至$v$,此时$e$贡献的价值为$1$
如果$c_e\geq2$,不停地选取两条路径$(u,a)$和$(u,b)$,那么我们可以把$(u,a)$和$(u,b)$换为$(a,b)$,如果$(a,b)$最终被决定为$a\rightarrow b$,那么还原过来就是$a\rightarrow u,u\rightarrow b$,否则是$b\rightarrow u,u\rightarrow a$,设$(u,c)$为$(u,a)$和$(u,b)$的交,那么$(u,c)$上的每一条边都一定能被双向经过,所以$e$贡献的价值为$2$,重复这个过程直至$c_e\lt2$,这样就构造性地说明了我们可以达到上界
我写得比较丑,毕竟是STL不用钱系列...
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
int h[2010],nex[4010],to[4010],dep[2010],fa[2010],fav[2010],M;
void add(int a,int b){
M++;
to[M]=b;
nex[M]=h[a];
h[a]=M;
}
void dfs(int x){
dep[x]=dep[fa[x]]+1;
for(int i=h[x];i;i=nex[i]){
if(to[i]!=fa[x]){
fa[to[i]]=x;
dfs(to[i]);
}
}
}
void col(int x,int y){
if(dep[x]<dep[y])swap(x,y);
while(dep[x]>dep[y]){
fav[x]++;
x=fa[x];
}
while(x!=y){
fav[x]++;
fav[y]++;
x=fa[x];
y=fa[y];
}
}
struct rt{
int x,y;
rt(int a=0,int b=0){x=a;y=b;}
};
bool operator==(rt a,rt b){return a.x==b.x&&a.y==b.y;}
int d[2010],n;
vector<rt>solve(vector<rt>v){
if(v.size()==0)return v;
int x,u,i;
for(x=1;x<=n;x++){
if(d[x]==1)break;
}
if(x>n)return v;
for(i=h[x];i;i=nex[i]){
if(d[to[i]]){
u=to[i];
break;
}
}
d[x]--;
d[u]--;
vector<rt>lx,nv;
vector<int>id;
int pos[2010];
memset(pos,-1,sizeof(pos));
for(i=0;i<(int)v.size();i++){
if(v[i].x==x||v[i].y==x){
lx.push_back(v[i]);
id.push_back(i);
}else{
nv.push_back(v[i]);
pos[i]=nv.size()-1;
}
}
if(lx.size()==0)return solve(v);
for(i=0;i+1<(int)lx.size();i+=2){
if(lx[i].y==x)swap(lx[i].x,lx[i].y);
if(lx[i+1].y==x)swap(lx[i+1].x,lx[i+1].y);
if(lx[i]==lx[i+1]){
if(v[id[i]]==v[id[i+1]])swap(v[id[i]].x,v[id[i]].y);
continue;
}
nv.push_back(rt(lx[i].y,lx[i+1].y));
pos[id[i]]=pos[id[i+1]]=nv.size()-1;
}
if(lx.size()&1){
if(lx[lx.size()-1].y==x)swap(lx[lx.size()-1].x,lx[lx.size()-1].y);
if(lx[lx.size()-1].y!=u){
nv.push_back(rt(u,lx[lx.size()-1].y));
pos[id[lx.size()-1]]=nv.size()-1;
}
}
nv=solve(nv);
for(i=0;i<(int)v.size();i++){
if(pos[i]!=-1&&!(v[i].x==nv[pos[i]].x||v[i].y==nv[pos[i]].y))swap(v[i].x,v[i].y);
}
return v;
}
vector<rt>v;
int main(){
int m,i,x,y,ans;
scanf("%d%d",&n,&m);
for(i=1;i<n;i++){
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
d[x]++;
d[y]++;
}
dfs(1);
for(i=1;i<=m;i++){
scanf("%d%d",&x,&y);
v.push_back(rt(x,y));
col(x,y);
}
v=solve(v);
ans=0;
for(i=2;i<=n;i++)ans+=min(2,fav[i]);
printf("%d\n",ans);
for(rt t:v)printf("%d %d\n",t.x,t.y);
}
[AGC025E]Walking on a Tree的更多相关文章
- K-D Tree
这篇随笔是对Wikipedia上k-d tree词条的摘录, 我认为解释得相当生动详细, 是一篇不可多得的好文. Overview A \(k\)-d tree (short for \(k\)-di ...
- 使控件具有 Tilt 效果
步骤1:添加类: /* Copyright (c) 2010 Microsoft Corporation. All rights reserved. Use of this sample source ...
- WinPhone学习笔记(四)——磁贴
对每个Windows Phone的使用者来说,给他们的第一印象就是大大小小的磁贴——Metro,本篇介绍的是Windows Phone的磁贴,提到的有开始菜单的磁贴,也有在App里面的磁贴. 开始菜单 ...
- java基础(1)-比较jdk5,jdk6,jdk7的新特性
jdk8已经出来好长时间了,这里自己学习时简单总结的jdk5,jdk6和jdk7的新特性:本文提纲: 一.jdk5的新特性 二.jdk6的新特性 三.jdk7的新特性 一.jdk5的新特性 首先简单介 ...
- 立即执行函数(IIFE)的理解与运用
作为JavaScript的常用语法,立即执行函数IIFE(Immediately-Invoked Function Expression)是值得我们认真去学习探究的. 一.创建函数的两种方式 我们先从 ...
- An NIO.2 primer--reference
Part 1: The asynchronous channel APIs The More New I/O APIs for the Java™ Platform (NIO.2) is one of ...
- (转载)XML Tutorial for iOS: How To Choose The Best XML Parser for Your iPhone Project
There are a lot of options when it comes to parsing XML on the iPhone. The iPhone SDK comes with two ...
- Windows Phone 8 ControlTiltEffect
/* Copyright (c) 2010 Microsoft Corporation. All rights reserved. Use of this sample source code is ...
- jQuery的使用及关于框架造型(转)
Introduction 正如jQuery所宣称的一样,Write Less, Do More.很多时候我们喜欢用它来解决问题.但增加一个库必然意味着更大的网络负担,意味着更高的页面初始载入时间.并且 ...
随机推荐
- pip 使用国内源
常用国内的pip源如下:阿里云 http://mirrors.aliyun.com/pypi/simple/中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple ...
- Vue2.0关于生命周期和钩子函数
Vue生命周期简介: Vue1.0+和Vue2.0在生命周期钩子上的区别还是很大的,如下: 代码验证: <!DOCTYPE html> <html> <head& ...
- mysql 基本操作练习
), sex ), age )); , '北京'); , '上海'); , '广州'); , '北京'); , '北京'); , '上海'); , '北京'); #(). 写出sql语句,查询所有年龄 ...
- Drupal7导入语言包
下载语言包 然后把包存放在profiles\standard\translations目录下,安装. 如果出现如下错误 1.错误有MySql数据库默认引擎innoDB引起,只要mysql\bin\my ...
- 也说JS脚本加载控制
问题背景 前端采用的 iframe + html 做后台管理系统.现在js.jquery插件非常多,每次页面都是引用就类似这样: <script src="../Scripts/jqu ...
- bzoj1040 内向树DP
2013-11-17 08:52 原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=1040 N个骑士,每个人有一个仇人,那么,每个骑士只有一个 ...
- C++ 异常~一 转
C++ 异常机制分析 阅读目录 C++异常机制概述 throw 关键字 异常对象 catch 关键字 栈展开.RAII 异常机制与构造函数 异常机制与析构函数 noexcept修饰符与noexce ...
- STL各个数据结构特点
STL容器特征总结 2011-11-09 11:10:50| 分类: STL|举报|字号 订阅 STL中顺序容器类和关联式容器类的主要特征如下:(1)Vector 1.内部数据结构:连续存储 ...
- 关于ES6(ES2015)开发记坑
ES2015(以下简称ES6)在开发过程中遇到的问题: 1,必须显示声明变量 //es5中可解释为全局变量 a=5; //es6中报错:a is not defined a=5 2,对于递归调用方式必 ...
- Webpack指南(一):安装,创建项目,配置文件,开发环境以及问题汇总
Webpack是一个现代 JavaScript 应用程序的静态模块打包器(module bundler).当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency gra ...