# 【BZOJ】1576 [Usaco2009 Jan]安全路经Travel

【算法】最短路树+(树链剖分+线段树)||最短路树+并查集

【题解】

<并查集>

#include<cstdio>
#include<algorithm>
#include<queue>
#include<cctype>
#include<cstring>
using namespace std;
const int maxn=400010,inf=0x3f3f3f3f;
struct edge{int u,v,w,from;}e[maxn*2];
int n,m,cnt,ans[maxn],first[maxn],tot,fa[maxn],f[maxn],deep[maxn],dis[maxn],d[maxn],c[maxn];
{
char c;int s=0,t=1;
while(!isdigit(c=getchar()))if(c=='-')t=-1;
do{s=s*10+c-'0';}while(isdigit(c=getchar()));
return s*t;
}
void insert(int u,int v,int w)
{tot++;e[tot].u=u;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
struct cyc{
int x,d;
bool operator < (const cyc &a)const{
return d>a.d;
}
};
priority_queue<cyc>q;
void dijkstra(){
memset(d,0x3f,sizeof(d));
deep[1]=d[1]=0;q.push((cyc){1,0});
while(!q.empty()){
cyc x=q.top();q.pop();
if(x.d!=d[x.x])continue;
for(int i=first[x.x];i;i=e[i].from)if(d[e[i].v]>d[x.x]+e[i].w){
d[e[i].v]=d[x.x]+e[i].w;
deep[e[i].v]=deep[x.x]+1;
f[e[i].v]=x.x;
q.push((cyc){e[i].v,d[e[i].v]});
}
}
}
struct cyc2{int u,v,num;}b[maxn];
bool cmp(cyc2 a,cyc2 b){return a.num<b.num;}
int main(){
int u,v,w;
for(int i=1;i<=m;i++){
insert(u,v,w);insert(v,u,w);
}
dijkstra();
for(int i=1;i<=tot;i+=2){
if(deep[e[i].u]<deep[e[i].v])swap(e[i].u,e[i].v);
if(d[e[i].u]!=d[e[i].v]+e[i].w)b[++cnt]=(cyc2){e[i].u,e[i].v,d[e[i].u]+d[e[i].v]+e[i].w};
}
sort(b+1,b+cnt+1,cmp);
for(int i=1;i<=n;i++)fa[i]=i;
f[1]=1;//初始父亲
for(int i=1;i<=cnt;i++){
int x=find(b[i].u),y=find(b[i].v);
while(x!=y){
if(deep[x]<deep[y])swap(x,y);
if(!ans[x])ans[x]=b[i].num;
x=fa[x]=find(f[x]);
}
}
for(int i=2;i<=n;i++)if(!ans[i])printf("-1\n");else printf("%d\n",ans[i]-d[i]);
return 0;
}
View Code

<树链剖分+线段树>

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int inf=0x3f3f3f3f,maxn=100010,maxm=200010;
struct edge{int u,from,v,w;}e[maxm*3];
struct tree{int l,r,tag;}t[maxn*3];
int n,m,tot=0,first[maxn],q[100010],fa[maxn],deep[maxn],d[maxn],top[maxn],pos[maxn],size[maxn],te[maxn],dfsnum=0;
bool mark[maxm*3],vis[maxn];
void insert(int u,int v,int w)
{tot++;e[tot].u=u;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;}
void spfa()
{
memset(d,0x3f,sizeof(d));
memset(mark,0,sizeof(mark));
memset(vis,0,sizeof(vis));
{
for(int i=first[x];i;i=e[i].from)
if(d[e[i].v]>d[x]+e[i].w)
{
int y=e[i].v;
d[y]=d[x]+e[i].w;
fa[y]=x;
mark[te[y]]=0;
te[y]=i;
mark[i]=1;
if(!vis[y]){q[tail++]=y;if(tail>100000)tail=0;}
vis[y]=1;
}
vis[x]=0;
}
//    for(int i=1;i<=n;i++)printf("fa[%d]=%d d[%d]=%d\n",i,fa[i],i,d[i]);
//    for(int i=1;i<=tot;i++)printf("[%d]%d %d %d\n",i,e[i].u,e[i].v,mark[i]);
}
void build(int k,int l,int r)
{
t[k].l=l;t[k].r=r;t[k].tag=inf;
if(l==r)return;
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
}
void dfs1(int x)
{
size[x]=1;
for(int i=first[x];i;i=e[i].from)
if(mark[i])
{
int y=e[i].v;
deep[y]=deep[x]+1;
dfs1(y);
size[x]+=size[y];
}
}
void dfs2(int x,int tp)
{
int k=0;
top[x]=tp;
pos[x]=++dfsnum;
for(int i=first[x];i;i=e[i].from)
if(mark[i]&&size[e[i].v]>size[k])k=e[i].v;
if(k==0)return;
dfs2(k,tp);
for(int i=first[x];i;i=e[i].from)
if(mark[i]&&e[i].v!=k)dfs2(e[i].v,e[i].v);
}
void seg_insert(int k,int l,int r,int x)
{
if(l<=t[k].l&&t[k].r<=r)
{
t[k].tag=min(t[k].tag,x);
return;
}
else
{
int mid=(t[k].l+t[k].r)>>1;
if(l<=mid)seg_insert(k<<1,l,r,x);
if(r>mid)seg_insert(k<<1|1,l,r,x);
}
}
{
if(t[k].l==t[k].r)return t[k].tag;
int mid=(t[k].l+t[k].r)>>1;
}
void solve_ins(int x,int y,int w)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])swap(x,y);
seg_insert(1,pos[top[x]],pos[x],w);
x=fa[top[x]];
}
if(pos[x]>pos[y])swap(x,y);
if(pos[x]<pos[y])seg_insert(1,pos[x]+1,pos[y],w);
}
int main()
{
scanf("%d%d",&n,&m);
int u,v,w;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
insert(u,v,w);insert(v,u,w);
}
spfa();
build(1,1,n);dfs1(1);dfs2(1,1);//printf("sldf\n");
for(int i=1;i<=m;i++)
if(!mark[i*2-1]&&!mark[i*2])solve_ins(e[i*2].u,e[i*2].v,d[e[i*2].u]+d[e[i*2].v]+e[i*2].w);
//    printf("asfjld\n");
for(int i=2;i<=n;i++)
{
if(ans>inf-100)ans=d[i]-1;
printf("%d\n",ans-d[i]);
}
return 0;
}
SPFA+链剖+线段树
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f,maxn=100010,maxm=200010;
struct edge{int u,from,v,w;}e[maxm*3];
struct tree{int l,r,tag;}t[maxn*3];
int n,m,tot=0,first[maxn],fa[maxn],deep[maxn],d[maxn],top[maxn],pos[maxn],size[maxn],te[maxn],dfsnum=0;
bool mark[maxm*3],vis[maxn];
void insert(int u,int v,int w)
{tot++;e[tot].u=u;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;}
struct Node{int x,d;}cyc;
priority_queue<Node>q;
bool operator <(Node a,Node b)
{return a.d>b.d;}
void dijkstra()
{
memset(d,0x3f,sizeof(d));
memset(mark,0,sizeof(mark));
d[1]=0;cyc.d=0;cyc.x=1;q.push(cyc);
while(!q.empty())
{
cyc=q.top();q.pop();
int x=cyc.x;
if(cyc.d!=d[x])continue;
for(int i=first[x];i;i=e[i].from)
if(d[e[i].v]>d[x]+e[i].w)
{
int y=e[i].v;
d[y]=d[x]+e[i].w;
cyc.x=y;cyc.d=d[y];q.push(cyc);
mark[te[y]]=0;
te[y]=i;mark[i]=1;
fa[y]=x;
}
}
//    for(int i=1;i<=n;i++)printf("fa[%d]=%d d[%d]=%d\n",i,fa[i],i,d[i]);
//    for(int i=1;i<=tot;i++)printf("[%d]%d %d %d\n",i,e[i].u,e[i].v,mark[i]);
}
void build(int k,int l,int r)
{
t[k].l=l;t[k].r=r;t[k].tag=inf;
if(l==r)return;
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
}
void dfs1(int x)
{
size[x]=1;
for(int i=first[x];i;i=e[i].from)
if(mark[i])
{
int y=e[i].v;
deep[y]=deep[x]+1;
dfs1(y);
size[x]+=size[y];
}
}
void dfs2(int x,int tp)
{
int k=0;
top[x]=tp;
pos[x]=++dfsnum;
for(int i=first[x];i;i=e[i].from)
if(mark[i]&&size[e[i].v]>size[k])k=e[i].v;
if(k==0)return;
dfs2(k,tp);
for(int i=first[x];i;i=e[i].from)
if(mark[i]&&e[i].v!=k)dfs2(e[i].v,e[i].v);
}
void seg_insert(int k,int l,int r,int x)
{
if(l<=t[k].l&&t[k].r<=r)
{
t[k].tag=min(t[k].tag,x);
return;
}
else
{
int mid=(t[k].l+t[k].r)>>1;
if(l<=mid)seg_insert(k<<1,l,r,x);
if(r>mid)seg_insert(k<<1|1,l,r,x);
}
}
{
if(t[k].l==t[k].r)return t[k].tag;
int mid=(t[k].l+t[k].r)>>1;
}
void solve_ins(int x,int y,int w)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])swap(x,y);
seg_insert(1,pos[top[x]],pos[x],w);
x=fa[top[x]];
}
if(pos[x]>pos[y])swap(x,y);
if(pos[x]<pos[y])seg_insert(1,pos[x]+1,pos[y],w);
}
int main()
{
scanf("%d%d",&n,&m);
int u,v,w;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
insert(u,v,w);insert(v,u,w);
}
dijkstra();
build(1,1,n);dfs1(1);dfs2(1,1);//printf("sldf\n");
for(int i=1;i<=m;i++)
if(!mark[i*2-1]&&!mark[i*2])solve_ins(e[i*2].u,e[i*2].v,d[e[i*2].u]+d[e[i*2].v]+e[i*2].w);
//    printf("asfjld\n");
for(int i=2;i<=n;i++)
{
if(ans>inf-100)ans=d[i]-1;
printf("%d\n",ans-d[i]);
}
return 0;
}
Dijkstra+链剖+线段树

Dijkstra+Heap 2.5s

SPFA+SLF 10s

SPFA TLE

posted @ 2017-08-31 08:48  ONION_CYC  阅读(...)  评论(...编辑  收藏