Description
The yearly Multi-University Training Contest is coming, and ?? had already prepared an interesting and challenging problem for all those intelligent brains. However, when he told teammates about his “wonderful idea”, it really shocked him that all of them, except himself, had already seen an existing problem with the same trick.So he need to rack his brain again.
But nothing is difficult for a willing heart. After thinking about it all through the night, he came up with a new problem:
The original rooted tree has n nodes, numbered from 1 to n. Each node has a value, all of these values form a permutation of [1,n]. We reset these values by the following way:
new value(P) = max{previous value(Q)|Q is in the subtree with root P}
Given the new tree(each node’s number, it’s neighbors and it’s value), your job is to restore its original appearance.
Note that the root of the given tree is unspecified.
Solution
发现title放成HDU访问量会上升
比赛的时候想出来了好高兴!!!
在ShinFeb面前口胡AC好高兴!!!
当了一下领导好高兴
不知为何感觉这题神似省选Day1rzz讲课的最后题Andrew Stankevich Contest 24 E,当时就口胡AC了。。
那题的题意:
对于一个1 n的排列a,定义a/i 为在该排列中去掉i后,剩下数相对大小和位置不变构成一个
1 n−1的排列。
如(1,3,5,2,6,4)/2=(1,2,4,5,3)
所有1≤i≤n的a/i顺序打乱后给出。
要求还原一个合法的排列a
觉得相似好像是因为都在找不变量?
首先这题根节点的权值一定是
然后权值为n的点会构成链对吧
根节点一定在这条链的一端对吧
直接用度判一下可以得到至多两个可以作为根的点
然后分开求
当然求val的过程就不很无脑了。
要用字典序贪心。
当然也是很简单的
对于点v,它的子节点
如果A[v]>mx则v的权值可以确定了对吧
否则我们可以得到关于
为了满足字典序,从大到小枚举val,开个堆随便贪贪心即可
不能理解为何赛场上没什么人A这题
本地测试一直RE,后来想弃坑了,随手一交,莫名AC。。
Code
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vec;
typedef pair<int,int> pii;
#define pb push_back
#define ph push
#define fi first
#define se second
template<class T>void rd(T &a){
a=0;char c;
while(c=getchar(),!isdigit(c));
do a=a*10+(c^48);
while(c=getchar(),isdigit(c));
}
template<class T>void nt(T x){
if(!x)return;
nt(x/10);
putchar(48+x%10);
}
template<class T>void pt(T x){
if(!x)putchar('0');
else nt(x);
}
template<class T>void Max(T &a,T b){
if(a<b)a=b;
}
template<class T>void Min(T &a,T b){
if(a==-1||a>b)a=b;
}
const int M=1e5+5;
int A[M];
struct Edge{int to,nxt;}G[M<<1];
int head[M],tot_edge,txt;
inline void add_edge(int from,int to){
G[tot_edge]=(Edge){to,head[from]};
head[from]=tot_edge++;
}
int val[M],res[M],n;
bool mark[M],responsible;
inline void dfs(int v,int fa){
if(!responsible)return;
int Mx=0;
for(int i=head[v];~i;i=G[i].nxt){
int to=G[i].to;
if(to==fa)continue;
dfs(to,v);
Max(Mx,A[to]);
}
if(A[v]>Mx)val[v]=A[v],mark[A[v]]=1;
if(A[v]<Mx)responsible=0;
}
inline bool check(int rt){
memset(val,0,sizeof(val));
memset(mark,0,sizeof(mark));
responsible=1;
dfs(rt,rt);
if(!responsible)return 0;
priority_queue<pii>query;
priority_queue<int>pque;
for(int i=n;i;--i)
if(!val[i])query.ph(pii(A[i],i));
for(int i=n;i;--i){//color node
if(mark[i])continue;
for(pii now;!query.empty();){
now=query.top();
if(now.fi>=i)
pque.ph(now.se),query.pop();
else break;
}
if(pque.empty())return 0;
int v=pque.top();pque.pop();
val[v]=i;
}
return 1;
}
int que[M],top,RT[5],d[M];
inline void gao(){
printf("Case #%d:",++txt);
cin>>n;
memset(d,0,sizeof(d));
memset(head,-1,sizeof(head));
top=tot_edge=0;
for(int i=1;i<=n;++i){
rd(A[i]);
if(A[i]==n)que[++top]=i;
}
for(int i=1,a,b;i<n;++i){
rd(a),rd(b);
add_edge(a,b),add_edge(b,a);
if(A[a]==n&&A[b]==n)++d[a],++d[b];
}
if(!top){puts(" Impossible");return;}
int c=res[0]=0;
if(top>1){
for(int i=1;i<=top;++i){
int v=que[i];
if(d[v]==1)RT[++c]=v;
if(d[v]>2||c>2||!d[v]){puts(" Impossible");return;}
}
if(c!=2){puts(" Impossible");return;}
}
else RT[++c]=que[1];
if(!c){puts(" Impossible");return;}
for(int i=1;i<=c;++i){
int v=RT[i];
bool flag=check(v);
if(flag){
if(!res[0])
for(int i=1;i<=n;++i)
res[i]=val[i];
else{
bool f=0;
for(int i=1;i<=n;++i){
if(val[i]>res[i])break;
if(val[i]<res[i]){f=1;break;}
}
if(f)for(int i=1;i<=n;++i)
res[i]=val[i];
}
res[0]=1;
}
}
if(!res[0]){puts(" Impossible");return;}
for(int i=1;i<=n;++i)
putchar(' '),pt(res[i]);
putchar('\n');
}
//#define LOCAL
int main(){
#ifdef LOCAL
freopen("data.in","r",stdin);
freopen("check.out","w",stdout);
#endif
int _;
for(cin>>_;_--;)gao();
return 0;
}