[Usaco2009 Jan]安全路经Travel BZOJ1576 Dijkstra+树链剖分+线段树

Posted winniechen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Usaco2009 Jan]安全路经Travel BZOJ1576 Dijkstra+树链剖分+线段树相关的知识,希望对你有一定的参考价值。

分析:

Dijkstra求最短路树,在最短路树上进行操作,详情可见上一篇博客:http://www.cnblogs.com/Winniechen/p/9042937.html

我觉得这个东西不压行写出了有点丑...之后写了一个压行后更丑的...

附上压行后的代码:

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
#define N 200005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define inf 0x3f3f3f3f
struct node
{
	int to,next,val;
}E[N<<2],e[N<<1];
int head[N],head1[N],cnt,cnt1,fa[N],a[N];
int dep[N],anc[N],siz[N],son[N],idx[N],b[N];
int dis[N],minn[N<<2],cov[N<<2],n,vis[N],c[N];
void add1(int x,int y,int z){E[cnt1].to=y;E[cnt1].next=head1[x];E[cnt1].val=z;head1[x]=cnt1++;}
void add(int x,int y,int z){e[cnt].to=y;e[cnt].next=head[x];e[cnt].val=z;head[x]=cnt++;}
void Dijkstra()
{
	memset(dis,0x3f,sizeof(dis));int num=0;
	priority_queue<pair<int ,int > >q;dis[1]=0;q.push(make_pair(0,1));
	while(!q.empty())
	{
		if(num==n)break;
		int x=q.top().second;q.pop();
		if(vis[x])continue;vis[x]=1;num++;
		for(int i=head1[x];i!=-1;i=E[i].next)
		{
			int to1=E[i].to;
			if(dis[to1]+E[i].val==dis[x])add(to1,x,E[i].val),add(x,to1,E[i].val);
		}
		for(int i=head1[x];i!=-1;i=E[i].next)
		{
			int to1=E[i].to;
			if(dis[x]+E[i].val<dis[to1])
			{
				dis[to1]=dis[x]+E[i].val;
				q.push(make_pair(-dis[to1],to1));
			}
		}
	}
}
void dfs1(int x,int from)
{
	fa[x]=from,dep[x]=dep[from]+1,siz[x]=1;
	for(int i=head[x];i!=-1;i=e[i].next)
	{
		int to1=e[i].to;
		if(to1!=from)
		{
			dfs1(to1,x);siz[x]+=siz[to1];
			if(siz[son[x]]<siz[to1])son[x]=to1;
		}
	}
}
int tims;
void dfs2(int x,int top)
{
	anc[x]=top;idx[x]=++tims;
	if(son[x])dfs2(son[x],top);
	for(int i=head[x];i!=-1;i=e[i].next)
	{
		int to1=e[i].to;
		if(to1!=fa[x]&&to1!=son[x])dfs2(to1,to1);
	}
}
void PushDown(int rt)
{
	if(cov[rt]!=inf)
	{
		int t=cov[rt];
		cov[rt<<1]=min(cov[rt<<1],t);
		minn[rt<<1]=min(minn[rt<<1],t);
		cov[rt<<1|1]=min(cov[rt<<1|1],t);
		minn[rt<<1|1]=min(minn[rt<<1|1],t);
		cov[rt]=inf;
	}
}
void build(int l,int r,int rt)
{
	minn[rt]=cov[rt]=inf;
	if(l==r)return ;int m=(l+r)>>1;
	build(lson);build(rson);
}
void Update(int L,int R,int c,int l,int r,int rt)
{
	if(L<=l&&r<=R)
	{
		minn[rt]=min(minn[rt],c);cov[rt]=min(cov[rt],c);
		return ;
	}
	PushDown(rt);int m=(l+r)>>1;
	if(L<=m)Update(L,R,c,lson);
	if(m<R)Update(L,R,c,rson);
}
int query(int x,int l,int r,int rt)
{
	if(l==r)return minn[rt];
	PushDown(rt);int m=(l+r)>>1;
	if(m>=x)return query(x,lson);
	else return query(x,rson);
}
void get_lca(int x,int y,int c)
{
	while(anc[x]!=anc[y])
	{
		if(dep[anc[x]]<dep[anc[y]])swap(x,y);
		Update(idx[anc[x]],idx[x],c,1,n,1);x=fa[anc[x]];
	}
	if(dep[x]>dep[y])swap(x,y);
	if(x!=y)Update(idx[x]+1,idx[y],c,1,n,1);
}
int main()
{
	int m;memset(head,-1,sizeof(head));memset(head1,-1,sizeof(head1));scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int x,y,z;scanf("%d%d%d",&x,&y,&z);
		add1(x,y,z);add1(y,x,z);a[i]=x,b[i]=y,c[i]=z;
	}
	Dijkstra();dfs1(1,0);dfs2(1,1);build(1,n,1);
	for(int i=1;i<=m;i++)
	{
		if(abs(dis[a[i]]-dis[b[i]])==c[i])continue;
		get_lca(a[i],b[i],dis[a[i]]+dis[b[i]]+c[i]);
	}
	for(int i=2;i<=n;i++)
	{
		int t=query(idx[i],1,n,1);
		t==inf?printf("-1\\n"):printf("%d\\n",t-dis[i]);
	}
	return 0;
}

  

以上是关于[Usaco2009 Jan]安全路经Travel BZOJ1576 Dijkstra+树链剖分+线段树的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1576 [Usaco2009 Jan]安全路经Travel

[Usaco2009 Jan]安全路经Travel BZOJ1576 Dijkstra+树链剖分+线段树

[USACO09JAN]安全出行Safe Travel

『USACO』安全路经Travel (bzoj 1576)

[USACO09JAN]安全出行Safe Travel

[usaco jan 09] 安全路径 travel [最短路径树]