bzoj 1576[Usaco2009 Jan]安全路经Travel

来源:互联网 发布:淘宝清除缓存在哪里 编辑:程序博客网 时间:2024/05/22 14:22

其实很久之前做的了,但是怎么都不过,今天拿出来竟然改一下就过了= =||

大概就是 给了一张无向图,问从起点开始到每个点的次短路。首先我们dij处理处最短路径树,然后在这上面搞事情处理一下。枚举所有的非树边 设起点u终点v 则这条边可以更新所有LCA(u,v)到v的点的次短路,就是dis[u]+len+dis[v]-dis[i] 这个i是正在处理的点 dis表示到根的距离 但是每条非树边可以更新的点有点多,所以我们要树剖维护这个过程 ,就是更新 所有LCA(u,v)到v的点 然后你就挂了 不能带着lca!  不能带着lca!  不能带着lca! 就这个把我挂哭了

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>#include<queue># define inf 0x3f3f3f3fusing namespace std;const int maxn=100000+10;struct node{int to,next,len,fr;bool o;}table[maxn<<2];struct tree{int x,l,r;int mn,lazy;}t[maxn<<2];int tot,head[maxn];void add(int a,int b,int c){table[++tot]=(node){b,head[a],c,a};head[a]=tot;}int n,m;char s[1<<25];inline long long read(){    static char *c=s;    if(c==s) fread(c,1,1<<25,stdin);    long long u=0;    while(*c<48) ++c;    while(*c>32) u=u*10+*c++-48;    return u;}typedef pair<int,int>Pair;priority_queue<Pair,vector<Pair>,greater<Pair> >Q;int d[maxn],fr[maxn];bool v[maxn];void dij(){    memset(d,0x3f,sizeof d);    d[1]=0; Q.push(make_pair(d[1],1));    while(!Q.empty())    {        Pair top=Q.top();        Q.pop();        int x=top.second;        if(v[x]) continue;        v[x]=1;        for(int i=head[x];i;i=table[i].next)        if(d[table[i].to]>d[x]+table[i].len)        {            d[table[i].to]=d[x]+table[i].len;            table[i].o=1;            table[fr[table[i].to]].o=0;            fr[table[i].to]=i;            Q.push(make_pair(d[table[i].to],table[i].to));        }    }}int f[maxn],dep[maxn],son[maxn],tp[maxn],w[maxn],pos[maxn],siz[maxn],cnt;int ans[maxn][20];void dfs1(int x){    dep[x]=dep[f[x]]+1;    siz[x]=1;    for(int i=1;i<=16;i++)    {        if(dep[x]<(1<<i)) break;        ans[x][i]=ans[ans[x][i-1]][i-1];        }    for(int i=head[x];i;i=table[i].next)    if(table[i].o&&table[i].to!=f[x])    {        f[table[i].to]=x;        ans[table[i].to][0]=x;        dfs1(table[i].to);        siz[x]+=siz[table[i].to];        if(siz[table[i].to]>siz[son[x]]) son[x]=table[i].to;    }}void dfs2(int x){    w[pos[x]=++cnt]=x;    if(x==son[f[x]]) tp[x]=tp[f[x]];    else tp[x]=x;    if(son[x]) dfs2(son[x]);    for(int i=head[x];i;i=table[i].next)    if(table[i].to!=son[x]&&table[i].o&&table[i].to!=f[x]) dfs2(table[i].to);}void maketree(int x,int l,int r){    t[x].l=l; t[x].r=r; t[x].lazy=t[x].mn=inf;    if(l==r) return ;    int mid=(t[x].l+t[x].r)>>1;    maketree(x<<1,l,mid);    maketree(x<<1|1,mid+1,r);}int LCA(int x,int y){    if(dep[x]<dep[y]) swap(x,y);    int l=dep[x]-dep[y];    for(int i=0;i<=16;i++)    if(l&(1<<i)) x=ans[x][i];    for(int i=16;i>=0;i--)    if(ans[x][i]!=ans[y][i]) x=ans[x][i],y=ans[y][i];    return x==y?x:ans[x][0];    }void pushdown(int x){    if(t[x].lazy==inf) return ;    int lc=x<<1,rc=x<<1|1;    t[lc].lazy=min(t[lc].lazy,t[x].lazy);    t[rc].lazy=min(t[rc].lazy,t[x].lazy);    t[lc].mn=min(t[lc].mn,t[x].lazy);    t[rc].mn=min(t[rc].mn,t[x].lazy);}void change(int x,int l,int r,int tar){    if(t[x].l==l&&t[x].r==r)    {        t[x].lazy=min(t[x].lazy,tar);        if(l==r) t[x].mn=min(t[x].mn,tar);        return ;    }    pushdown(x);    int mid=(t[x].l+t[x].r)>>1;    if(r<=mid) change(x<<1,l,r,tar);    else if(l>mid) change(x<<1|1,l,r,tar);    else change(x<<1,l,mid,tar),change(x<<1|1,mid+1,r,tar);}void modify(int x,int lca,int tar){    int fx=tp[x];    while(dep[fx]>dep[lca])    {        change(1,pos[fx],pos[x],tar);        x=f[fx],fx=tp[x];    }    if(x!=lca) change(1,pos[lca]+1,pos[x],tar);}int search(int x,int pos){    if(t[x].l==t[x].r) return t[x].mn;    pushdown(x);    int mid=(t[x].l+t[x].r)>>1;    if(pos<=mid) return search(x<<1,pos);    else return search(x<<1|1,pos);    }int main(){    scanf("%d%d",&n,&m);    int a,b,c;    for(int i=1;i<=m;i++)    {        a=read(); b=read(); c=read();        add(a,b,c); add(b,a,c);    }    dij();    dfs1(1);    dfs2(1);    maketree(1,1,cnt);    for(int i=1;i<=tot;i++)    if(!table[i].o)    {        int t=LCA(table[i].fr,table[i].to);        modify(table[i].to,t,d[table[i].fr]+table[i].len+d[table[i].to]);    }    for(int i=2;i<=n;i++)    {        int x=search(1,pos[i]);        if(x==inf) puts("-1");        else printf("%d\n",x-d[i]);    }    return 0;}


1 0
原创粉丝点击