luogu P2680 运输计划
开始T啊,T啊,T啊
以为写的常数大,然后就在卡常
死活卡不过去啊QAQQQQQQ
然后发现自己的复杂度多乘了个logn啊啊啊啊啊
其实吧每组的lca预处理处来就好了啊啊啊啊啊
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
const int maxn = 400007;
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' || c > '9'){if(c == '-')f = -1;c = getchar();}
while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar();
return x * f;
}
int l,r;
struct Node {
int v,w,next;
}edge[maxn << 1];
int Lca[maxn];
int head[maxn],num = 0;
inline void add_edge(int u,int v,int w) {
edge[++ num].v = v;edge[num].w = w,edge[num].next = head[u];head[u] = num;
}
int n,m;int dis[maxn],deep[maxn],fa[maxn][22];
void dfs(int x,int f) {
deep[x] = deep[f] + 1;fa[x][0] = f;
for(int i = 0;fa[x][i];++ i) {
fa[x][i + 1] = fa[fa[x][i]][i];
}
for(int i = head[x];i;i = edge[i].next) {
int v = edge[i].v;
if(v == f)continue;
dis[v] = dis[x] + edge[i].w;
dfs(v,x);
}
}
int lca(int x,int y) {
if(deep[x] > deep[y]) std::swap(x,y);
for(int i = 18;i >= 0;-- i)
if(deep[x] <= deep[fa[y][i]] ) y = fa[y][i];
if(x == y) return x;
for(int i = 18;i >= 0;-- i)
if(fa[x][i] != fa[y][i]) x = fa[x][i],y = fa[y][i];
return fa[x][0];
}
int U[maxn],V[maxn];
inline int Dis(int i) {
return dis[U[i]] + dis[V[i]] - 2 * dis[Lca[i]];
}
int hav[maxn],H[maxn];
int tmp_max,numm = 0,qoq;
bool flag = false;
void Dfs(int x,int f) {
if(flag == true) return;
for(int i = head[x];i;i = edge[i].next) {
int v = edge[i].v;
if(v == f) continue;
Dfs(v,x);
if(hav[v] == numm) {
if(tmp_max - edge[i].w <= qoq ) {
flag = true;return;
}
}
hav[x] += hav[v];
}
}
bool check(int x) {
flag = false; qoq = x;
for(int i = 1;i <= n;++ i) hav[i] = 0;
tmp_max = 0,numm = 0;
for(int i = 1;i <= m;++ i) {
int d = Dis(i);
if(d > x) {
numm ++;
tmp_max = std::max(tmp_max,d);
hav[U[i]]++,hav[V[i]] ++;
hav[Lca[i]] -= 2;
}
}
//printf("%d\n",lca(2,5));
if(!num) return true;
Dfs(1,0);
return flag;
}
int main() {
n = read(),m = read();
for(int a,b,c,i = 1;i < n;++ i) {
a = read(),b = read(),c = read() ;
add_edge(a,b,c);add_edge(b,a,c);
}
dfs(1,0);
for(int i = 1;i <= m;++ i)
U[i] = read(),V[i] = read();
for(int i = 1;i <= m;++ i)
Lca[i] = lca(U[i],V[i]),r = std::max(r,Dis(i));
int ans = 0 ;
while(l <= r) {
int mid = l + r >> 1;
if(check(mid)) ans = mid,r = mid - 1;
else l = mid + 1;
}
printf("%d\n",ans);
return 0;
}