题意: 现在有n个点,有一个起始点,你要求出从起始点到其他点的最短路,那么这就是一个很简单的最短路问题,但是麻烦的地方在建图,普通的建图这里肯定是不行的。因为这里有三种操作,第一 从u到v 加一条边,权值 为w 第二 从u到 l,r 的点都可以,权值为w ,第三 从 l,r 到u点,权值为w 。那么对于这种区间,我们可以用线段树建图的方法,
这里方法是:
建立两颗线段树
A线段树每个节点和其父亲节点之间有一条边,边权为0
B线段树每个节点和其两个儿子节点之间有一条边,边权为0
B线段树的每个叶节点和A线段树的每个叶节点之间有一条边,边权为0
对于每一个op==1 的操作,我们建一条从A线段树叶节点到B线段树叶节点的边,边权为w
对于每一个op==2的操作,我们建一条从A线段树叶节点到B线段树区间节点的边,边权为w 因为B线段树是从上向下建,那么就相当于u节点可以到B区间节点的区间内的每一个节点。
对于每一个op==3 的操作,我们建一条从A线段树区间节点到B线段树叶子节点的边,边权为w 因为A线段树我们是从下向上建,那么就相当于A区间节点内的每一个点都可以到达B点的叶子节点。
最后跑一个最短路就可以了。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2000005;
const int maxm = 10000005;
typedef long long LL;
const LL inf = 0x3f3f3f3f3f3f3f3f;
int ls[maxn],rs[maxn],L[maxn],R[maxn],num;
int ver[maxm],he[maxn],ne[maxm],tot;
LL cost[maxm];
void add( int x,int y,LL w ){
ver[++tot] = y;
ne[tot] = he[x];
he[x] = tot;
cost[tot] = w;
}
int buildup( int l,int r ){
if( l == r ){
return L[l] = R[l] = l;
}
int id = ++num;
int mid = l+r>>1;
L[id] = l;R[id] = r;
ls[id] = buildup( l,mid );
rs[id] = buildup( mid+1,r );
add( ls[id],id,0 );
add( rs[id],id,0 );
return id;
}
int builddown( int l,int r ){
if( l == r ){
return L[l] = R[l] = l;
}
int id = ++num;
L[id] = l;R[id] = r;
int mid = l+r>>1;
ls[id] = builddown( l,mid );
rs[id] = builddown( mid+1,r );
add( id,ls[id],0 );
add( id,rs[id],0 );
return id;
}
void update1( int l,int r,int v,LL w,int x ){
if( R[x] < l || L[x] > r ) return;
if( l <= L[x] && r >= R[x] ){
add( x,v,w );
return;
}
update1( l,r,v,w,ls[x] );
update1( l,r,v,w,rs[x] );
}
void update2( int l,int r,int u,LL w,int x ){
if( R[x] < l || L[x] > r ) return;
if( l <= L[x] && r >= R[x] ){
add( u,x,w );
return;
}
update2( l,r,u,w,ls[x] );
update2( l,r,u,w,rs[x] );
}
priority_queue< pair<LL,int>,vector< pair<LL,int> >,greater< pair<LL,int> > > que2;
LL dist[maxn];
int vis[maxn];
void dijkstra( int S,int n ){
while( que2.size() ) que2.pop();
memset( dist,0x3f,sizeof(dist) );
dist[S] = 0;
que2.push( make_pair( 0,S ) );
while( que2.size() ){
int x = que2.top().second;
que2.pop();
//if( x == T ) break;
if( vis[x] ) continue;
vis[x] = 1;
for( int cure = he[x];cure;cure = ne[cure] ){
int y = ver[cure];
if( vis[y] ) continue;
if( dist[y] > dist[x] + cost[cure] ){
dist[y] = dist[x] + cost[cure];
que2.push( make_pair( dist[y],y ) );
}
}
}
}
int main(){
int n,q,s;
scanf("%d%d%d",&n,&q,&s);
num = n;
int root1 = buildup( 1,n ),root2 = builddown(1,n);
for( int i = 1;i <= q;i++ ){
int op,u,v,w,l,r;
scanf("%d",&op);
if( op == 1 ){
scanf("%d%d%d",&u,&v,&w);
update2( v,v,u,w,root2 );
}else if( op == 2 ){
scanf("%d%d%d%d",&u,&l,&r,&w);
update2( l,r,u,w,root2 );
}else{
scanf("%d%d%d%d",&v,&l,&r,&w);
update1( l,r,v,w,root1 );
}
}
dijkstra(s,num);
for( int i = 1;i <= n;i++ ){
if( dist[i] != inf )printf("%I64d ",dist[i]);
else printf("-1 ");
}
return 0;
}