题目
P4149-(求一条边数最少的权值和为K的简单路径权 的边数 点分治模板)
输入样例#1:
4 3
0 1 1
1 2 2
1 3 4
输出样例#1:
2
n≤200000,K≤1000000
P4149-(求一条边数最少的权值和为K的简单路径权 的边数 点分治模板)
日你????啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊

可以use[d[l].dep+d[r].dep]+=f。按照正常的点分治来。。我他妈一直WA啊啊啊。
一定要调出来,这也太难受了。。。但是尺取的时候 复杂度可能会达到很高。。

不这样的话可以 子树一个一个的计算。不是像以前一样getd()的到一大堆再减去子树内部不合法的情况。一个一个的计算时,先计算完毕后,再把计算的这个子树更新进去,就不会发生重复了。然后一个树算完之后,把这个树都清空。清空操作和更新操作可以用一个函数,memset的话也许会T。
到底如何计算呢:每次计算子树x之前,前x-1颗的子树t[i]值会被更新好,t[i]代表dis是i时的最少边;
cal(): ans=min(ans,t[K-dis[x]+dep[x])。
modify: t[dis[x]]=min(t[dis[x]],dep[x]);

日你????啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#define foru(i,a,b) for(int i=a;i<=b;++i)
#define m(a,b) memset(a,b,sizeof a)
#define en '\n'
using namespace std;
typedef long long ll;
const int N=2e5+5,M=1e6+5,INF=0x3f3f3f3f;
template<class T>void rd(T &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch<'0'||ch>'9')  {f|=(ch=='-');ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=f?-x:x;
    return;
}
struct Edge{int to,len,nex;}edge[N<<1];
int head[N],tot;
void add(int from,int to,int len)
{
    edge[++tot]=(Edge){to,len,head[from]};head[from]=tot;
    edge[++tot]=(Edge){from,len,head[to]};head[to]=tot;
}
int sum,root,ans;
int sz[N],mx[N],vis[N];
void getroot(int x,int fa)
{
    sz[x]=1,mx[x]=0;
    for(int i=head[x];i;i=edge[i].nex)
    {
        int y=edge[i].to;
        if(vis[y]||y==fa) continue;
        getroot(y,x);
        sz[x]+=sz[y];
        mx[x]=max(mx[x],sz[y]);
    }
    mx[x]=max(mx[x],sum-sz[x]);
    if(mx[x]<mx[root]) root=x;
}
int dis[N],dep[N];
int t[M],K;//t[i]表示前面有个点已经走了距离i的最小边数.
void cal(int x,int fa)
{
    if(dis[x]<=K)
        ans=min(ans,t[K-dis[x]]+dep[x]);
    for(int i=head[x];i;i=edge[i].nex)
    {
        int y=edge[i].to;
        if(vis[y]||y==fa) continue;
        dep[y]=dep[x]+1,dis[y]=dis[x]+edge[i].len;
        cal(y,x);
    }
}
void modify(int x,int fa,int f)
{
    if(dis[x]<=K)
    {
        if(f==1) t[dis[x]]=min(t[dis[x]],dep[x]);
        else t[dis[x]]=INF;
        for(int i=head[x];i;i=edge[i].nex)
        {
            int y=edge[i].to;
            if(vis[y]||y==fa) continue;
            modify(y,x,f);
        }
    }
}
void work(int x)
{
    vis[x]=1;
    for(int i=head[x];i;i=edge[i].nex)
    {
        int y=edge[i].to;
        if(vis[y]) continue;
        dep[y]=1,dis[y]=edge[i].len;
        cal(y,x);
        modify(y,x,1);
    }
    for(int i=head[x];i;i=edge[i].nex)
    {
        int y=edge[i].to;
        if(vis[y]) continue;
        modify(y,x,-1);
    }
    sum=sz[x],root=0;
    for(int i=head[x];i;i=edge[i].nex)
    {
        int y=edge[i].to;
        if(vis[y]) continue;
        sum=sz[y],root=0;
        getroot(y,x);
        work(root);
    }
}
int main()
{
    int n;rd(n),rd(K);
    foru(i,1,K) t[i]=INF;
    foru(i,1,n-1)
    {
        int u,v,w;rd(u),rd(v),rd(w);
        ++u,++v;
        add(u,v,w);
    }
    sum=n,root=0,mx[0]=INF,ans=INF;
    getroot(1,-1);
    work(root);
    printf("%d\n",ans==INF?-1:ans);
}

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-06-24
  • 2022-12-23
  • 2021-06-08
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-12-13
  • 2022-12-23
相关资源
相似解决方案