F. Nastya and Time Machine(搜索 构造)
程序员文章站
2022-07-12 13:51:12
...
http://codeforces.com/contest/1341/problem/F
题意:
给出一棵树,现在要求从点1出发遍历所有的结点一遍后再回到点1。
操作:
到相邻点,时间加1
到当前点的之前时间(时光机),但是同一个点同一个时间只能出现一次。
求一个方案使得最大时间最少
解析:
手模最大时间为最大度。
到达一个点时间为,到其第一个儿子。返回时其儿子的时间为,返回点的时间为。
当当前点时间为时,则变为(为了之后返回时为)
代码:
/*
* Author : Jk_Chen
* Date : 2020-05-02-22.01.39
*/
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
void test(){cerr<<"\n";}
template<typename T,typename... Args>void test(T x,Args... args){cerr<<"> "<<x<<" ";test(args...);}
const LL mod=1e9+7;
const int maxn=1e5+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/
#define rep_e(i,p,u) for(int i=head[p],u=to[i];i;i=nex[i],u=to[i])
int head[maxn],to[maxn<<1],nex[maxn<<1],now;
void add(int a,int b){
nex[++now]=head[a];head[a]=now;to[now]=b;
}
int deg[maxn];
void init_edge(){
memset(head,0,sizeof head);
now=0;
}
/*_________________________________________________________edge*/
vector<pill>ans;
int mx=-1;
void dfs(int p,int fa,int ti){
int tmp=ti;
ans.pb({p,ti});
int son=deg[p];
if(p!=1)son--;
rep_e(i,p,u){
if(u==fa)continue;
if(ti==mx){
ti-=son+1;
ans.pb({p,ti});
}
dfs(u,p,ti+1);
ti++;
ans.pb({p,ti});
}
if(ti!=tmp-1&&fa)
ans.pb({p,tmp-1});
}
int main(){
int n=rd;
rep(i,1,n-1){
int a=rd,b=rd;
add(a,b);add(b,a);
deg[a]++,deg[b]++;
}
rep(i,1,n)mx=max(mx,deg[i]);
dfs(1,0,0);
printf("%d\n",ans.size());
for(auto P:ans){
printf("%d %d\n",P.fi,P.se);
}
return 0;
}
/*_________________________________________________________end*/