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. ISO 学习笔记 2015-03-15

    Objective--C 一 关键字 @property 定义变量函数 @synthesize 实现变量函数 二 函数 alloc 分配内存 init 初始化 new 替代上面两个函数 分配内存,并且 ...

  2. linux驱动(一)

    编写模块必须先声明下面两句: #include <linux/module.h>               //这个头文件包含了许多符号与函数的定义,这些符号与函数多与加载模块有关 #i ...

  3. SQL Server中count(*), count(col), count(1)的对比

    让我们先看一下BOL里面对count(*)以及count(col)的说明: COUNT(*) 返回组中的项数.包括 NULL 值和重复项. COUNT(ALL expression) 对组中的每一行都 ...

  4. sql 自身连接

    "select table1.field1, table2.field1 from table table1, table table2 where table1.id=table2.par ...

  5. C#winform程序安装时自动卸载新版本覆盖旧版本

    vs2005为winform程序做的安装包.在以有程序旧版本的机子上用新版本的安装包安装软件时提示  “以经安装该产品的另一个版本.无法继续安装此版本........” 在安装部署项目中设“Remov ...

  6. UIImageView 的 contentMode

    UIViewContentModeScaleToFill, // 按设置尺寸 - 填充 UIViewContentModeScaleAspectFit, // 按设置尺寸 - 等比例填充, 有边界 U ...

  7. 安装plsql

    sqlplus能登录,服务器.网络.tns配置应该都是好的,应该就是plsql本身的问题 问下安装路径在哪? 注意安装路径中不能有括号,不要安装在C:\Program Files (x86)目录下面

  8. LightOj_1287 Where to Run

    题目链接 题意: 有n个街口和m条街道, 你后边跟着警察,你需要进行大逃亡(又是大爱的抢银行啊),在每个街口你都有≥1个选择, 1)停留在原地5分钟. 2)如果这个街口可以到xi这个街口, 并且, 通 ...

  9. 形形色色Node工程Angular2

    最近项目要用的 一些无关紧要的文件夹, demo是一些示例, dist是webpack打包后发布的代码,server是用node启动服务,typings和tsconfig是一些ts配置. npm in ...

  10. [cocos2dx]计算scrollview元素的index

    scrollview的原生代码没有提供元素对齐功能 通过下面介绍的index计算方法以及scrollview自带的设置位置方法 void setContentOffsetInDuration(CCPo ...