Codeforces 786B(区间图最短路)
Posted aaddvvaanntteezz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 786B(区间图最短路)相关的知识,希望对你有一定的参考价值。
题意
给定一张$n$个点的有向图,有三种连边方式- $a->b$,代表$a$向$b$连一条有向边
- $a->[l,r]$.代表$a$向区间$[l,r]$的所有点连一条有向边
- $[l,r]->a$.代表区间$[l,r]$向$a$的连一条有向边
题解
区间图最短路裸题,建出两颗线段树维护整个区间,一个区间可以用线段树表示为$log(n)$个点,这样就把建图时间压缩成$mlogn$了,然后跑最短路就行了。查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 4e6+5;
const int mod = 1e9+7;
const ll inf = 0x3f3f3f3f3f3f3f3f;
ll qpow(ll a,ll b){ll res=1;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
struct graph
{
int head[maxn],nxt[maxn<<1],to[maxn<<1],w[maxn<<1],sz;
void init(){memset(head,-1,sizeof(head));}
graph(){init();}
void push(int a,int b,int c){nxt[sz]=head[a],to[sz]=b,w[sz]=c,head[a]=sz++;}
int& operator[](const int a){return to[a];}
}g;
int n,m,s,tot;
struct Segment_tree
{
int id[maxn];
void build(int root,int l,int r,bool flag){
id[root]=++tot;
if(l==r){
if(flag)
g.push(id[root],l,0);
else g.push(l,id[root],0);
return ;
}
int mid = l+r>>1;
build(root<<1,l,mid,flag);
build(root<<1|1,mid+1,r,flag);
if(flag){
g.push(id[root],id[root<<1],0);
g.push(id[root],id[root<<1|1],0);
}
else {
g.push(id[root<<1],id[root],0);
g.push(id[root<<1|1],id[root],0);
}
}
void addedge(int root,int l,int r,int ul,int ur,int u,int w,bool flag){//区间连边[ul,ur]->u
if(l>=ul&&r<=ur){
if(!flag){
g.push(id[root],u,w);
}
else g.push(u,id[root],w);
return;
}
int mid = l+r>>1;
if(ul<=mid)addedge(root<<1,l,mid,ul,ur,u,w,flag);
if(ur>mid)addedge(root<<1|1,mid+1,r,ul,ur,u,w,flag);
}
}in,out;
ll dist[maxn];
struct node
{
int x;
ll cost;
node(int a,ll b):x(a),cost(b){};
friend bool operator < (node a,node b){
return a.cost>b.cost;
}
};
bool vis[maxn];
void dij()
{
memset(dist,0x3f,sizeof(dist));
priority_queue<node>q;
q.push(node(s,0));
dist[s]=0;
while(!q.empty()){
node now = q.top();
q.pop();
if(dist[now.x]<now.cost)continue;
vis[now.x]=1;
for(int i = g.head[now.x];~i;i = g.nxt[i]){
if(vis[g[i]])continue;
if(dist[g[i]]>dist[now.x]+g.w[i]){
dist[g[i]]=dist[now.x]+g.w[i];
q.push(node(g[i],dist[g[i]]));
}
}
}
for(int i = 1;i <= n;++i){
if(dist[i]==inf)printf("-1 ");
else printf("%lld ",dist[i]);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("simple.in", "r", stdin);
freopen("simple.out", "w", stdout);
#endif
int type,v,l,r,u,c;
scanf("%d%d%d",&n,&m,&s);
tot=n;
in.build(1,1,n,1);
out.build(1,1,n,0);
for(int i = 1;i <= m;++i){
scanf("%d",&type);
if(type==1){
scanf("%d%d%d",&v,&u,&c);
g.push(v,u,c);
in.addedge(1,1,n,u,u,v,c,1);
}
else if(type==2){
scanf("%d%d%d%d",&v,&l,&r,&c);
in.addedge(1,1,n,l,r,v,c,1);
}
else {
scanf("%d%d%d%d",&v,&l,&r,&c);
out.addedge(1,1,n,l,r,v,c,0);
}
}
dij();
return 0;
}
以上是关于Codeforces 786B(区间图最短路)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 786B - Legacy(线段树优化建图)
786B - Legacy(线段树 + 最短路)线段树优化建图
Educational Codeforces Round 102 E. Minimum Path(分层图最短路)