社区讨论
求助,第十三个点T了
P2680[NOIP 2015 提高组] 运输计划参与者 9已保存回复 12
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 12 条
- 当前快照
- 1 份
- 快照标识符
- @mi7w1jmd
- 此快照首次捕获于
- 2025/11/21 04:32 4 个月前
- 此快照最后确认于
- 2025/11/21 06:31 4 个月前
CPP
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<ctime>
using namespace std;
const int N=3e5+100;
struct edge{
int s,e,v,next;
}ed[(N<<1)];
int n,m,tot,numv,numedv,root;
int head[N],a[N],b[N],sum[N],si[N],deep[N],f[25][N],cnt[N],lca[N],edv[N],v[N];
inline int LCA(int x,int y)
{
if (deep[x]>deep[y]) swap(x,y);
for (int i=20;i>=0;i--)
if (deep[f[i][y]]>=deep[x]) y=f[i][y];
if (x==y) return x;
for (int i=20;i>=0;i--)
if (f[i][y]!=f[i][x])
{
x=f[i][x];
y=f[i][y];
}
return f[0][x];
}
inline void dfs2(int x,int fa)
{
sum[x]=cnt[x];
for (int i=head[x];i;i=ed[i].next)
if (ed[i].e!=fa)
{
dfs2(ed[i].e,x);
sum[x]+=sum[ed[i].e];
if (sum[x]>=numv&&sum[ed[i].e]>=numv)
edv[++numedv]=i;
}
return ;
}
inline bool work(int x)
{
numv=0;numedv=0;
memset(sum,0,sizeof(sum));
memset(cnt,0,sizeof(cnt));
int maxx=0,maxv=0;
for (int i=1;i<=m;i++)
if (si[i]>x)
{
maxv=max(maxv,si[i]);
v[++numv]=i;
}
for (int i=1;i<=numv;i++)
{
cnt[a[v[i]]]++;
cnt[b[v[i]]]++;
cnt[f[0][lca[v[i]]]]-=2;
}
dfs2(root,0);
for (int i=1;i<=numedv;i++)
maxx=max(maxx,ed[edv[i]].v);
if (maxv-maxx<=x) return 1;
return 0;
}
inline void dfs1(int x,int fa)
{
deep[x]=deep[fa]+1;
f[0][x]=fa;
for (int i=1;(1<<i)<=deep[x];i++)
f[i][x]=f[i-1][f[i-1][x]];
for (int i=head[x];i;i=ed[i].next)
if (ed[i].e!=fa)
{
sum[ed[i].e]=sum[x]+ed[i].v;
dfs1(ed[i].e,x);
}
return ;
}
inline void add(int s,int e,int v)
{
ed[++tot]=(edge){s,e,v,head[s]};
head[s]=tot;
return ;
}
inline int read()
{
int ans=0,p=1;
char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') p=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){ans=ans*10+ch-'0';ch=getchar();}
return ans*p;
}
int main()
{
srand(time(NULL));
n=read();m=read();
for (int i=1;i<=n-1;i++)
{
int s,e,v;
s=read();e=read();v=read();
add(s,e,v);
add(e,s,v);
}
root=rand()%n+1;
dfs1(root,0);
int vmax=0;
for (int i=1;i<=m;i++)
{
a[i]=read();b[i]=read();
lca[i]=LCA(a[i],b[i]);
si[i]=sum[a[i]]+sum[b[i]]-(sum[lca[i]]<<1);
vmax=max(vmax,si[i]);
}
int l=0,r=vmax,mid=(l+r+1)>>1;
while (l<=r)
{
if (work(mid)) r=mid-1;
else l=mid+1;
mid=(l+r+1)>>1;
}
printf("%d\n",mid);
return 0;
}
倍增求LCA,T第十三个点
试了一下欧拉序求LCA,65分,树剖50分
求大佬赐教
回复
共 12 条回复,欢迎继续交流。
正在加载回复...