8.19 T1

过不了大样例

查不出错。。。可能想错了

wawawa爆零了

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;
const int N=500005;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	return f*x;
}
inline void Min(int &x,int y) {if(x>y)x=y;}
inline void Max(int &x,int y) {if(x<y)x=y;}
int jue(int x,int y) {return x>y?x-y:y-x;}
vector<int>v[N];
int n,k,fa[N],ban[N];
int to[N],nxt[N],hd[N],w[N],tot;
inline void add(int x,int y,int z) {
    to[++tot]=y;w[tot]=z;nxt[tot]=hd[x];hd[x]=tot;
}

int dep[N],dis[N],mxdep;
int mi[N];
void dfs(int x) {
    for(int i=hd[x];i;i=nxt[i]) {
        int y=to[i];
        if(y==fa[x]) continue;
        dep[y]=dep[x]+1;
        v[dep[y]].push_back(y);
        Max(mxdep,dep[y]);
        dis[y]=dis[x]+w[i];
        Min(mi[dep[y]],dis[y]);
        dfs(y);
    }
}   
int main() {
    memset(mi,0x3f,sizeof(mi));
    n=read();k=read();
    for(int i=2,z;i<=n;i++) {
        fa[i]=read();z=read();ban[i]=read();
        add(fa[i],i,z);
    }   
    dep[1]=0;mi[0]=0;
    v[0].push_back(0);
    dfs(1);
    puts("0");
    for(int s=1;s<=mxdep;s++) {
        for(int j=0;j<v[s].size();j++) {
            if(!ban[v[s][j]]) 
                for(int last=0;last<=mxdep;last++) 
                    Min(dis[v[s][j]],mi[last]+jue(s,last)*k);
            Min(mi[s],dis[v[s][j]]);
        } 
    }
    for(int i=2;i<=n;i++) 
        printf("%d\n",dis[i]);
    return 0;
}

不知所错。。。

去撸正解吧


额怎么说呢。。。想的又和正解挺像的

就是每层开vector 存一个当前层最小值

有一个点没有想到

就是可以记录一个bestpos最优点,它后面的层都可以用它更新,正确性证明(口糊):

我们按层数从小到大推,设之前的bestpos为 i ,新的bestpos为 j (i到1的距离>j到1的距离) ,那么对后面的层 k 来说 dep[k]-dep[i] > dep[k]-dep[j] && i到1的距离>j到1的距离 ∴ 之后跳 j 一定比跳 i 优

还有个小优化 输入边权的时候如果能坐车就和k取min

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;
const int N=500005;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	return f*x;
}
inline void Min(int &x,int y) {if(x>y)x=y;}
inline void Max(int &x,int y) {if(x<y)x=y;}
vector <int> v[N];
int n,k,fa[N],ban[N];
int to[N],nxt[N],hd[N],w[N],tot;
inline void add(int x,int y,int z) {
    to[++tot]=y;w[tot]=z;nxt[tot]=hd[x];hd[x]=tot;
}

int dep[N],dis[N],mxdep;
int best[N],bestpos;
int get(int x,int y) {return best[x]+(y-x)*k;}
int main() {
    memset(best,0x3f,sizeof(best));//每一层的最小值
    n=read();k=read();
    for(int i=2,z;i<=n;i++) {
        fa[i]=read();z=read();ban[i]=read();
        dep[i]=dep[fa[i]]+1;
        Max(mxdep,dep[i]);
        if(!ban[i]) Min(z,k);//优化
        add(fa[i],i,z);
    }   
    for(int i=1;i<=n;i++) v[dep[i]].push_back(i); 
    for(int i=0;i<=mxdep;i++) {//这个循环是第i层已经完成,在第i层推向第i+1层
        for(int j=0;j<v[i].size();j++) {
            int y=v[i][j];
            Min(best[dep[y]],dis[y]);
        }
        int mi=best[i];
        for(int j=0;j<v[i].size();j++)
            if(!ban[v[i][j]])
                Min(dis[v[i][j]],mi);
        if(i&&get(bestpos,i)>get(i,i)) bestpos=i;
        for(int j=0;j<v[i].size();j++) {
            int x=v[i][j];
            for(int s=hd[x];s;s=nxt[s]) {
                int y=to[s];
                dis[y]=dis[x]+w[s];
                if(!ban[y]) Min(dis[y],get(bestpos,i+1));
            }
        }
    }
    for(int i=1;i<=n;i++) 
        printf("%d\n",dis[i]);
    return 0;
}
/*
4 3
1 7 1
1 5 0
2 1 0
*/
posted @ 2020-08-19 16:45  ke_xin  阅读(23)  评论(0编辑  收藏  举报