[CF1296F] Berland Beauty

[CF1296F] Berland Beauty

题意

给你一颗大小为 \(n\) 的无根树,树边的边权尚未确定。现在你从 \(m\) 个人中得知在 \((u,v)\) 这条路径(最短路径)上的最小边权为 \(w\)。请你构造一种方案满足这 \(m\) 个人的条件,如果不存在,请输出 \(-1\)

分析

我们显然可以先把边权按照从小到大排序,而后构造一种最优方案即把这条路径上的所有边都赋值为 \(w\)。这样我们可以使得每条路径上的最小值都尽可能满足题面的要求。而后我们检验是否合法。使用 LCA 维护即可。

代码

#includebitsstdc++.h
using namespace std;
const int N=1e4+7;
struct node{int u,v,w;}a[N];
int f[N][50];
int head[N],to[N],nxt[N];
int fat[N];
int dis[N],dep[N];
int cnt;
int n,m;
int num[N];
int w[N];
void add(int u,int v){
	cnt++;to[cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
}
int xx;
void dfs(int x,int fa){
	++xx;
	if (xx  1e6) exit(0);
	for(int i=head[x];i;i=nxt[i]){
		int y=to[i];
		if(y==fa) continue;
        num[y]=(i+1)2;
		dep[y]=dep[x]+1;fat[y]=x;dfs(y,x);
	}
}
void init(){
	for(int i=1;i=n;i++) f[i][0]=fat[i];
	for(int j=1;j=20;j++){
		for(int i=1;i=n;i++){
			f[i][j]=f[f[i][j-1]][j-1];
		}
	}
}
int lca(int x, int y) {
    if (dep[x]  dep[y])
        swap(x, y);
    if (dep[x] != dep[y]) {
        for (int i = 20; i = 0; i--)
            if (dep[f[x][i]]  dep[y])
                x = f[x][i];
        x = f[x][0];
    }
    if (x == y)
        return x;
    for (int i = 20; i = 0; i--)
        if (f[x][i] != f[y][i])
            x = f[x][i], y = f[y][i];
    return f[x][0];
}
void modify(int u,int v,int val){
    int _lca=lca(u,v);
    while(u!=_lca) w[num[u]]=val,u=f[u][0];
    while(v!=_lca) w[num[v]]=val,v=f[v][0];
}
int query(int u,int v){
    int _lca=lca(u,v);
    int res=0x3f3f3f3f;
    while(u!=_lca) res=min(res,w[num[u]]),u=f[u][0];
    while(v!=_lca) res=min(res,w[num[v]]),v=f[v][0];
    return res;
}
int main(){
    scanf(%d,&n);
    for(int i=1;i=n-1;i++){
        int x,y;
        scanf(%d%d,&x,&y);
        add(x,y),add(y,x);
    }
    dfs(1,0);
    init();
    scanf(%d,&m);
    for(int i=1;i=m;i++){
        scanf(%d%d%d,&a[i].u,&a[i].v,&a[i].w);
    }
    sort(a+1,a+1+m,[](const node a,const node b){return a.wb.w;});
     for(int i=1;i=m;i++) printf(%dn,a[i].w);
      for(int i=1;i=n;i++) printf(%dn,num[i]);
    for(int i=1;i=m;i++) modify(a[i].u,a[i].v,a[i].w);
    bool flag=0;
    for(int i=1;i=m;i++){
    	 printf(%d ,query(a[i].u,a[i].v));
        if(query(a[i].u,a[i].v)!=a[i].w){flag=1;break;}
    }
    if(flag) printf(-1n);
    else{
        for(int i=1;i=n-1;i++){
            printf(%d ,w[i]w[i]1);
        }
         printf(%dn,w[n-1]w[n-1]1);
    }
    return 0;
}
posted @ 2023-07-25 14:18  Zimo_666  阅读(5)  评论(0编辑  收藏  举报