3694: 最短路

Time Limit: 5 Sec  Memory Limit: 256 MB
Submit: 67  Solved: 34
[Submit][Status][Discuss]

Description

给出一个n个点m条边的无向图,n个点的编号从1~n,定义源点为1。定义最短路树如下:从源点1经过边集T到任意一点i有且仅有一条路径,且这条路径是整个图1到i的最短路径,边集T构成最短路树。 给出最短路树,求对于除了源点1外的每个点i,求最短路,要求不经过给出的最短路树上的1到i的路径的最后一条边。
 

Input

第一行包含两个数n和m,表示图中有n个点和m条边。
接下来m行,每行有四个数ai,bi,li,ti,表示图中第i条边连接ai和bi权值为li,ti为1表示这条边是最短路树上的边,ti为0表示不是最短路树上的边。

Output

输出n-1个数,第i个数表示从1到i+1的要求的最短路。无法到达输出-1。

Sample Input

5 9
3 1 3 1
1 4 2 1
2 1 6 0
2 3 4 0
5 2 3 0
3 2 2 1
5 3 1 1
3 5 2 0
4 5 4 0

Sample Output

6 7 8 5

HINT

对于100%的数据,n≤4000,m≤100000,1≤li≤100000

Source

题解:
首先,先处理出最短路树中每个点i距源点1的最短距离dis[i]。
 因为要求不经过最短路树的最后一条边,所以要到一个点,必须要从和这个点在同一个环中的另外一边绕过去。
例如:设我们要到u点,我们还有不在最短路树上的两个点x,y。t为LCA(x,y)。假如u点在y到t的路径上,我们既然不能从1经过t到u,那我们只有从1 -> t -> x -> y ->u。这样我们可以用dis[x]+val[x][y]+dis[y]-dis[u]来更新ans。因为dis[u]是不变的,所以我们可以最后去减去dis[u]。之前只用维护dis[x]+val[x][y]+dis[y]即可。
 #include<bits/stdc++.h>
using namespace std;
#define MAXN 4010
#define MAXM 100010
#define INF 1e9
struct node
{
int begin,end,value,next;
}edge[MAXN*];
struct NODE
{
int left,right,mn,tag;
}tree[MAXN*];
int cnt,Head[MAXN],n,size[MAXN],deep[MAXN],P[MAXN][],dis[MAXN],pos[MAXN],belong[MAXN],s1[MAXM],s2[MAXM],s3[MAXM],SIZE;
bool vis[MAXN];
void addedge(int bb,int ee,int vv)
{
edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].value=vv;edge[cnt].next=Head[bb];Head[bb]=cnt;
}
void addedge1(int bb,int ee,int vv)
{
addedge(bb,ee,vv);addedge(ee,bb,vv);
}
int read()
{
int s=,fh=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')fh=-;ch=getchar();}
while(ch>=''&&ch<=''){s=s*+(ch-'');ch=getchar();}
return s*fh;
}
void dfs1(int u)
{
int i,v;
size[u]=;vis[u]=true;
for(i=Head[u];i!=-;i=edge[i].next)
{
v=edge[i].end;
if(vis[v]==false)
{
deep[v]=deep[u]+;
dis[v]=dis[u]+edge[i].value;
P[v][]=u;
dfs1(v);
size[u]+=size[v];
}
}
}
void Ycl()
{
int i,j;
for(j=;(<<j)<=n;j++)
{
for(i=;i<=n;i++)
{
if(P[i][j-]!=-)P[i][j]=P[P[i][j-]][j-];
}
}
}
void dfs2(int u,int chain)
{
int k=,i,v;
pos[u]=++SIZE;belong[u]=chain;
for(i=Head[u];i!=-;i=edge[i].next)
{
v=edge[i].end;
if(deep[v]>deep[u]&&size[v]>size[k])k=v;
}
if(k==)return;
dfs2(k,chain);
for(i=Head[u];i!=-;i=edge[i].next)
{
v=edge[i].end;
if(deep[v]>deep[u]&&v!=k)dfs2(v,v);
}
}
int LCA(int x,int y)
{
int i,j;
if(deep[x]<deep[y])swap(x,y);
for(i=;(<<i)<=deep[x];i++);i--;
for(j=i;j>=;j--)if(deep[x]-(<<j)>=deep[y])x=P[x][j];
if(x==y)return x;
for(j=i;j>=;j--)
{
if(P[x][j]!=-&&P[x][j]!=P[y][j])
{
x=P[x][j];
y=P[y][j];
}
}
return P[x][];
}
void Build(int k,int l,int r)
{
tree[k].left=l;tree[k].right=r;tree[k].tag=INF;
if(l==r){tree[k].mn=INF;return;}
int mid=(l+r)/;
Build(k*,l,mid);
Build(k*+,mid+,r);
}
void Pushup(int k)
{
int l=k*,r=k*+;
tree[k].mn=min(tree[l].mn,tree[r].mn);
}
void Pushdown(int k)
{
int l=k*,r=k*+;
if(tree[k].tag!=INF)
{
tree[l].tag=min(tree[l].tag,tree[k].tag);
tree[r].tag=min(tree[r].tag,tree[k].tag);
tree[l].mn=min(tree[l].mn,tree[k].tag);
tree[r].mn=min(tree[r].mn,tree[k].tag);
tree[k].tag=INF;
}
}
void Change(int k,int l,int r,int C)
{
if(l<=tree[k].left&&tree[k].right<=r){tree[k].tag=min(tree[k].tag,C);tree[k].mn=min(tree[k].mn,C);return;}
Pushdown(k);
int mid=(tree[k].left+tree[k].right)/;
if(r<=mid)Change(k*,l,r,C);
else if(l>mid)Change(k*+,l,r,C);
else {Change(k*,l,mid,C);Change(k*+,mid+,r,C);}
Pushup(k);
}
void Solve_change(int x,int f,int C)
{
while(belong[x]!=belong[f])
{
Change(,pos[belong[x]],pos[x],C);
x=P[belong[x]][];
}
if(x!=f)Change(,pos[f]+,pos[x],C);
}
int Query(int k,int l,int r)
{
if(l<=tree[k].left&&tree[k].right<=r)return tree[k].mn;
Pushdown(k);
int mid=(tree[k].left+tree[k].right)/;
if(r<=mid)return Query(k*,l,r);
else if(l>mid)return Query(k*+,l,r);
else return min(Query(k*,l,mid),Query(k*+,mid+,r));
}
int Solve_query(int x,int f)
{
int MN=INF;
while(belong[x]!=belong[f])
{
MN=min(MN,Query(,pos[belong[x]],pos[x]));
x=P[belong[x]][];
}
if(x!=f)MN=min(MN,Query(,pos[f]+,pos[x]));
return MN;
}
int ask(int k,int lr)
{
if(tree[k].left==tree[k].right)return tree[k].mn;
Pushdown(k);
int mid=(tree[k].left+tree[k].right)/;
if(lr<=mid)return ask(k*,lr);
else return ask(k*+,lr);
}
int main()
{
int m,tot,i,a,b,l,t,lca,C;
n=read();m=read();
tot=;
memset(Head,-,sizeof(Head));cnt=;
for(i=;i<=m;i++)
{
a=read();b=read();l=read();t=read();
if(t==)
{
s1[++tot]=a;s2[tot]=b;s3[tot]=l;
}
else addedge1(a,b,l);
}
memset(P,-,sizeof(P));SIZE=;
dfs1();Ycl();
dfs2(,);
Build(,,n);
//for(i=1;i<=n;i++)Change(1,pos[i],pos[i],dis[i]);
for(i=;i<=tot;i++)
{
lca=LCA(s1[i],s2[i]);
C=dis[s1[i]]+dis[s2[i]]+s3[i];
Solve_change(s1[i],lca,C);
Solve_change(s2[i],lca,C);
}
for(i=;i<=n;i++)
{
//t=Solve_query(i,1);
t=Query(,pos[i],pos[i]);
//t=ask(1,pos[i]);
if(t==INF)printf("-1 ");
else printf("%d ",t-dis[i]);
}
return ;
}

Bzoj 3694: 最短路 树链剖分的更多相关文章

  1. BZOJ 3531 [Sdoi2014]旅行 树链剖分+动态开点线段树

    题意 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我们用 ...

  2. BZOJ 3531: [Sdoi2014]旅行 [树链剖分]

    3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1685  Solved: 751[Submit][Status] ...

  3. BZOJ 2243: [SDOI2011]染色 [树链剖分]

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6651  Solved: 2432[Submit][Status ...

  4. [BZOJ - 2819] Nim 【树链剖分 / DFS序】

    题目链接: BZOJ - 2819 题目分析 我们知道,单纯的 Nim 的必胜状态是,各堆石子的数量异或和不为 0 .那么这道题其实就是要求求出树上的两点之间的路径的异或和.要求支持单点修改. 方法一 ...

  5. BZOJ.4515.[SDOI2016]游戏(树链剖分 李超线段树)

    BZOJ 洛谷 每次在路径上加的数是个一次函数,容易看出是树剖+李超线段树维护函数最小值.所以其实依旧是模板题. 横坐标自然是取个确定的距离标准.取每个点到根节点的距离\(dis[i]\)作为\(i\ ...

  6. BZOJ 2243 染色(树链剖分好题)

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 7971  Solved: 2990 [Submit][Stat ...

  7. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

  8. NOIP 2015 BZOJ 4326 运输计划 (树链剖分+二分)

    Description 公元 年,人类进入了宇宙纪元. L 国有 n 个星球,还有 n− 条双向航道,每条航道建立在两个星球之间,这 n− 条航道连通了 L 国的所有星球. 小 P 掌管一家物流公司, ...

  9. BZOJ 2243: [SDOI2011]染色 (树链剖分+线段树合并)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243 树链剖分的点剖分+线段树.漏了一个小地方,调了一下午...... 还是要细心啊! 结 ...

随机推荐

  1. 基于HTML5和JSP实现的图片Ajax上传和预览

    本文对如何实现使用Ajax提交"multipart/form"格式的表单数据,已经如何在图片上传之前,在浏览器上进行预览.使用的主要相关技术HTML5的FILE API,XMLHt ...

  2. IQueryable接口与IEnumberable区别

    IEnumerable<T> 泛型类在调用自己的SKip 和 Take 等扩展方法之前数据就已经加载在本地内存里了,而IQueryable<T> 是将Skip ,take 这些 ...

  3. [简历] PHP 技能关键字列表

    本技能关键字列表是从最近招聘PHP的数百份JD中统计出来的,括号中是出现的词频.如果你的简历要投递给有机器(简历分选系统)和不如机器(不懂技术的HR)筛选简历环节的地方,请一定从下边高频关键词中选择5 ...

  4. swift 与 OC 混合编程

    原文地址:http://www.cocoachina.com/swift/20150608/12025.html 一.解决问题 Swift项目需要使用封装好的Objective-c组件.第三方类库,苹 ...

  5. 数据库 - FMDB

    FMDB 是基于 SQLite 封装的 面向对对象(OC) 的API. FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API FMDB 需要libsqli ...

  6. 240多个jQuery插件

    概述 jQuery 是继 prototype 之后又一个优秀的 Javascript 框架.其宗旨是—写更少的代码,做更多的事情.它是轻量级的 js 库(压缩后只有21k) ,这是其它的 js 库所不 ...

  7. Linux 下编译、安装、配置 QT

    转自Linux 下编译.安装.配置 QT 注意:编译安装耗时费力,且很容易出错,要不断调整编译参数,不推荐使用,否则这将会是一个纠结痛苦的过程. 打算做嵌入式图像处理,计划方案嵌入式Linux+Ope ...

  8. c#中总是提示“在代码运行时或者在禁用“只要一个进程中断,就中断所有进程”选项时,不允许进行更改。

    但是根据它提示的修改方法,还是提示这个. “此选项可在“工具”->“选项”->“调试”中启用.” 根本不起作用,后来试着,要这样操作: 工具->选项->调试->编辑并继续 ...

  9. 使用php-emoji类让网页显示emoji表情

    需要的材料: php-emoji类库的下载地址:https://github.com/iamcal/php-emoji 代码示例:(该代码来自官网) <?php include('emoji.p ...

  10. OA学习笔记-003-Hibernate3.6配置

    一.jar包:核心包, 必须包, jpa, c3p0, jdbc antlr-2.7.6.jarc3p0-0.9.1.jarcommons-collections-3.1.jardom4j-1.6.1 ...