社区讨论

95分,被卡长求调

P2680[NOIP 2015 提高组] 运输计划参与者 3已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@mivicxia
此快照首次捕获于
2025/12/07 17:16
2 个月前
此快照最后确认于
2025/12/10 17:35
2 个月前
查看原帖
CPP
#include<bits/stdc++.h>

using namespace std;

const int N = 3*1e5+10;
vector<pair<int,int> > g[N];
inline int read()
{
	int s=0,w=1;
	char c=getchar();
	while (!isdigit(c))
	{
		if (c=='-')	w=-1;
		c=getchar();
	}
	while (isdigit(c))
	{
		s=s*10+c-'0';
		c=getchar();
	}
	return s*w;
}
int fa[N][20],deep[N];
int dist[N],path_len[N];
vector<pair<int,int> > ed;
int val[N],n,k,max_len;

void dfs(int u,int f,int w){
    deep[u] = deep[f]+1;
    dist[u] = dist[f]+w;
    fa[u][0] = f;
    for(int i = 1;i<20;i++) fa[u][i] = fa[fa[u][i-1]][i-1];
    for(auto [v,we]:g[u]){
        if(v==f) continue;
        dfs(v,u,we);
    }
}

int lca(int x,int y){
    if(deep[x]<deep[y]) swap(x,y);//确保X的深度大于y
    for(int i = 19;i>=0;i--){
        if(deep[fa[x][i]]>=deep[y]){
            x = fa[x][i];//保证深度相同
        }
    }
    if(x==y) return x;//如果x和y相同,直接返回
    //x,y深度相同,同时往上跳
    for(int i = 19;i>=0;i--){
        if(fa[x][i]!=fa[y][i]){
            x = fa[x][i];
            y = fa[y][i];
        }
    }
    return fa[x][0];//!!!
}

void sum(int u,int f){
    for(auto [v,we]:g[u]){
        if(v==f) continue;
        sum(v,u);
        val[u]+=val[v];
    }
}
bool check(int mid){
    int cnt = 0;
    max_len = 0;
    memset(val,0,sizeof(val));
    for(int i = 0;i<k;i++){
        if(path_len[i]>mid){
            cnt++;
            max_len = max(max_len,path_len[i]);
            auto [u,v] = ed[i];
            int l = lca(u,v);
            val[u]++;
            val[v]++;
            val[l]-=2;
        }
    }
    sum(1,0);
    for(int i = 2;i<=n;i++){
        int tmp = dist[i]-dist[fa[i][0]];
        if(val[i]==cnt && (max_len-tmp)<=mid) return 1;
    }
    return 0;

}
int main(){
    n = read(),k = read();
    for(int i = 1,x,y,w;i<n;i++){
        x = read(),y = read(),w = read();
        g[x].push_back({y,w});
        g[y].push_back({x,w});
    }
    dfs(1,0,0);
    max_len = 0;
    for(int i = 0,u,v;i<k;i++){
        u = read(),v = read();
        ed.push_back({u,v});
        path_len[i] = dist[u]+dist[v]-2*dist[lca(u,v)];
        max_len = max(max_len,path_len[i]);
    }
    int l = -1,r = max_len+1;
    while(l+1<r){
        int mid = l+r>>1;
        if(check(mid)) r = mid;
        else l = mid;
    }
    cout<<r;

    return 0;
}

回复

3 条回复,欢迎继续交流。

正在加载回复...