社区讨论

求助,第十三个点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 条回复,欢迎继续交流。

正在加载回复...