「BalkanOI 2018 Day1」Minmaxtree

每个点都有一个最大和最小权值的限制。

然后每一个权值的限制都必须要取到。

每个点显然可以直接让他取到最大或最小权值。

可以想到每个点匹配一个权值。

不就是一个二分图吗。。。

每个点连向最大和最小权值,然后跑dinic,输出方案,当然本题匈牙利可以跑过。

接下来就是要求每个点的权值限制:可以用LCT直接链标记,也可以离线下来,排序后,依次加入,用一个并查集跳过已经访问过的点。

#include<bits/stdc++.h>
#define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q)
#define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q)
#define mem(a,b) memset(a,b,sizeof a )
#define debug(a) cerr<<#a<<' '<<a<<"___"<<endl
using namespace std;
void in(int &r){
static char c;
r=0;
while(c=getchar(),!isdigit(c));
do r=(r<<1)+(r<<3)+(c^48);
while(c=getchar(),isdigit(c));
}
const int mn=70010;
int head[mn<<1],to[mn<<3],ne[mn<<3],cnt1,W[mn<<3],n;
#define link1(a,b) link_edge1(a,b),link_edge1(b,a)
#define link_edge1(a,b) to[++cnt1]=b,ne[cnt1]=head[a],head[a]=cnt1
#define travel(x) for(int q(head[x]);q;q=ne[q])
struct edge{
int x,y;
}e[mn];
void link(int x,int y);
int cnt;
void pre_dfs(int f,int x){
travel(x)if(to[q]!=f)e[++cnt]={x,to[q]},link(to[q],cnt+n),link(cnt+n,x),pre_dfs(x,to[q]);
}
int son[mn<<1][2],fa[mn<<1];
bool mark[mn<<1];
int Min[mn<<1],Max[mn<<1];
int minv[mn<<1],maxv[mn<<1];
bool noroot(int x){
return x==son[fa[x]][0]||x==son[fa[x]][1];
}
void rotate(int x){
int y=fa[x],z=fa[y],d=x==son[y][1];
if(noroot(y))son[z][y==son[z][1]]=x;
son[y][d]=son[x][!d];
fa[son[x][!d]]=y;
son[x][!d]=y;
fa[x]=z,fa[y]=x;
}
int sta[mn<<1],tp;
void res(int x){
if(!x)return;
swap(son[x][0],son[x][1]);
mark[x]^=1;
}
void min_mark(int x,int v){
if(!x)return;
if(!minv[x])minv[x]=v;
else minv[x]=max(v,minv[x]);
if(!Min[x])Min[x]=v;
else Min[x]=max(Min[x],v);
}
void max_mark(int x,int v){
if(!x)return;
if(!maxv[x])maxv[x]=v;
else maxv[x]=min(v,maxv[x]);
if(!Max[x])Max[x]=v;
else Max[x]=min(Max[x],v);
}
void push_down(int x){
int ls=son[x][0],rs=son[x][1];
if(mark[x]){
res(ls);
res(rs);
mark[x]=0;
}
if(Min[x]){
min_mark(ls,Min[x]);
min_mark(rs,Min[x]);
Min[x]=0;
}
if(Max[x]){
max_mark(ls,Max[x]);
max_mark(rs,Max[x]);
Max[x]=0;
}
}
void splay(int x){
tp=0;
int now=x;
while(noroot(now))sta[++tp]=now,now=fa[now];
sta[++tp]=now;
dep(q,tp,1)push_down(sta[q]);
while(noroot(x)){
int y=fa[x];
if(noroot(y))(x==son[y][1])==(y==son[fa[y]][1])?rotate(y):rotate(x);
rotate(x);
}
}
void access(int x){
for(int y=0;x;y=x,x=fa[x])splay(x),son[x][1]=y;
}
void makeroot(int x){
access(x),splay(x),res(x);
}
void split(int x,int y){
makeroot(x);
access(y),splay(y);
}
void link(int x,int y){
fa[x]=y;
}
int px[mn],ll[mn],rr[mn],hd=0;
void solve(){
int a,b,v,Q;
in(Q);
char c;
while(Q--){
while(c=getchar(),!isalpha(c));
in(a),in(b),in(v);
px[++hd]=v;
split(a,b);
if(c=='M')max_mark(b,v);
else min_mark(b,v);
}
}
void get_min_max(){
sort(px+1,px+hd+1);
rep(q,1,n-1){
splay(n+q);
ll[q]=minv[n+q],rr[q]=maxv[n+q];
}
}
void clear_edge(){
rep(q,1,n)head[q]=0;
cnt1=1;
}
void link_edge(int x,int y,int z){
to[++cnt1]=y,ne[cnt1]=head[x],head[x]=cnt1;
W[cnt1]=z;
}
void link_w(int x,int y,int z){
link_edge(x,y,z);
link_edge(y,x,0);
}
int S,T,tot_node;
void build_graph(){
S=n-1+hd+1;
T=S+1;
tot_node=T;
rep(q,1,n-1)link_w(S,q,1);
rep(q,1,hd)link_w(q+n-1,T,1);
rep(q,1,n-1){
if(ll[q])ll[q]=lower_bound(px+1,px+hd+1,ll[q])-px,link_w(q,ll[q]+n-1,1);
if(rr[q])rr[q]=lower_bound(px+1,px+hd+1,rr[q])-px,link_w(q,rr[q]+n-1,1);
}
}
int depth[mn<<1],cur[mn<<1],que[mn<<1];
bool bfs(){
rep(q,1,tot_node)depth[q]=-1;
int l=0,r=0;
que[++r]=S;
depth[S]=1;
while(l<r){
int now=que[++l];
travel(now)if(depth[to[q]]==-1&&W[q]){
depth[to[q]]=depth[now]+1;
que[++r]=to[q];
if(to[q]==T)return 1;
}
}
return 0;
}
int dfs(int x,int flow){
if(!flow||x==T)return flow;
int used=0;
for(int &q=cur[x];q;q=ne[q])if(depth[to[q]]==depth[x]+1){
int fl=dfs(to[q],min(flow-used,W[q]));
W[q]-=fl;
W[q^1]+=fl;
used+=fl;
if(used==flow)return used;
}
if(!used)depth[x]=-1;
return used;
}
void bipartite_match(){
while(bfs()){
rep(q,1,tot_node)cur[q]=head[q];
dfs(S,1e9);
}
}
bool mk[mn];
const int Rand_lim=1e9;
void out(){
rep(w,1,n-1){
bool ok=0;
travel(w)if(to[q]!=S&&to[q]>=n&&W[q]==0){
printf("%d %d %d\n",e[w].x,e[w].y,px[to[q]-(n-1)]);
mk[to[q]-(n-1)]=1;
ok=1;
}
if(!ok)printf("%d %d %d\n",e[w].x,e[w].y,rr[w]?px[rr[w]]:px[ll[w]]);
}
}
int main(){
freopen("minmaxtree.in","r",stdin);
freopen("minmaxtree.out","w",stdout);
srand(time(NULL));
int a,b;
in(n);
rep(q,2,n)in(a),in(b),link1(a,b);
pre_dfs(0,1); solve(); get_min_max(); clear_edge(); build_graph(); bipartite_match(); out();
return 0;
}

「BalkanOI 2018 Day1」Minmaxtree的更多相关文章

  1. 「BalkanOI 2018 Day1」Election

    「BalkanOI 2018 Day1」Election 记C为1,T为-1,\(sum[i]\)为\(i\)点的前缀和. 对于询问\([l,r]\),分两步计算答案. 要求所有点的\(sum[i]- ...

  2. 「BalkanOI 2018 Day2」Parentrises

    「BalkanOI 2018 Day2」Parentrises part1 显然可以直接贪心. 右括号记-1,左括号记1. 默认起始全部绿色,不染色. 策略如下: 从左往右扫,如果右括号个数大于左括号 ...

  3. LOJ#2351. 「JOI 2018 Final」毒蛇越狱

    LOJ#2351. 「JOI 2018 Final」毒蛇越狱 https://loj.ac/problem/2351 分析: 首先有\(2^{|?|}\)的暴力非常好做. 观察到\(min(|1|,| ...

  4. 【LOJ】#3032. 「JOISC 2019 Day1」馕

    LOJ#3032. 「JOISC 2019 Day1」馕 处理出每个人把馕切成N段,每一段快乐度相同,我们选择第一个排在最前的人分给他的第一段,然后再在未选取的的人中选一个第二个排在最前的切一下,并把 ...

  5. 【LOJ】#3031. 「JOISC 2019 Day1」聚会

    LOJ#3031. 「JOISC 2019 Day1」聚会 听说随机可过? 我想了很久想了一个不会被卡的做法,建出前\(u - 1\)个点的虚树,然后找第\(u\)个点的插入位置,就是每次找一条最长链 ...

  6. 【LOJ】#3030. 「JOISC 2019 Day1」考试

    LOJ#3030. 「JOISC 2019 Day1」考试 看起来求一个奇怪图形(两条和坐标轴平行的线被切掉了一个角)内包括的点个数 too naive! 首先熟练的转化求不被这个图形包含的个数 -- ...

  7. 「JOISC 2014 Day1」巴士走读

    「JOISC 2014 Day1」巴士走读 将询问离线下来. 从终点出发到起点. 由于在每个点(除了终点)的时间被过来的边固定,因此如果一个点不被新的边更新,是不会发生变化的. 因此可以按照时间顺序, ...

  8. 「JOISC 2014 Day1」 历史研究

    「JOISC 2014 Day1」 历史研究 Solution 子任务2 暴力,用\(cnt\)记录每种权值出现次数. 子任务3 这不是一个尺取吗... 然后用multiset维护当前的区间,动态加, ...

  9. [loj 6496]「雅礼集训 2018 Day1」仙人掌

    传送门 Description 给出一张 \(n\)个点 \(m\)条边的无向连通图,其中每条边至多属于一个简单环,保证没有自环,可能有重边.你需要为其中每条边定向,其中第 \(i\)个点的出度不能超 ...

随机推荐

  1. 【Java笔记】Java分包问题

    这个图讲的很清晰,转自-http://www.bubuko.com/infodetail-2219664.html

  2. [git]初始化项目文件到git分支

    将本地和远程仓库关联并push本地项目 1.VCS -> import into Version Control  ->  Create Git Repository 选择项目文件   2 ...

  3. 初遇NFT-IPFS

    初遇NFT-IPFS 本次学习如何使用Hardhat框架制作可预售的NFT并利用IPFS存储元数据. NFT简介 NFT全称Non-fungible Token(即非同质化通证).不可分割性(目前有碎 ...

  4. MySQL数据操作与查询笔记 • 【第3章 DDL 和 DML】

    全部章节   >>>> 本章目录 3.1 使用 DDL 定义数据库表结构 3.1.1 SQL 简介 3.1.2 维护数据库和创建数据表 3.2 使用 DDL 维护数据库表结构 ...

  5. 分布式抽奖秒杀系统,DDD架构设计和实现分享

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.用大项目,贯穿知识体系 写CRUD.堆API.改屎山⛰,熬多少个996也只是成为重复的螺丝 ...

  6. iNeuOS工业互联网操作系统,增加DTU与平台实时交互的应用场景

    目       录 1.      概述... 2 2.      平台演示... 2 3.      硬件设置... 2 4.      应用过程... 3 1.   概述 DTU向下连接硬件传感器 ...

  7. Linux上天之路(十)之Linux磁盘管理

    主要内容 磁盘介绍 磁盘管理 磁盘限额 逻辑卷管理 磁盘阵列 1. 磁盘介绍 硬盘最基本的组成部分是由坚硬金属材料制成的涂以磁性介质的盘片,不同容量硬盘的盘片数不等.每个盘片有两面,都可记录信息.盘片 ...

  8. 深入理解Java虚拟机之自己编译JDK

    题外话 最近在阅读<深入理解Java虚拟机>,其中有一小节实战是自己编译JDK,实际操作下来后遇到问题不少,为此特地记录,也希望可以给大家带来一些参考! 前置准备 平台及工具:Window ...

  9. 1.配置桥接,并抓包验证 2.实现免密登录 3.修改登录端口: 22-》2222 4.不允许root用户远程登录 5.创建用户sshuser1,并设置密码,且只允许sshuser1远程ssh登录

    1.配置桥接:  抓包时如果有ens160的ICMP,说明我们的桥接搭建成功通过桥接访问到了ens160(这里忘加图片了) (1)创建一个桥接设备和会话 (2)添加设备和会话到桥接设备上 (3)启动从 ...

  10. leetcode 51. N皇后 及 52.N皇后 II

    51. N皇后 问题描述 n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击. 上图为 8 皇后问题的一种解法. 给定一个整数 n,返回所有不同的 n 皇后 ...