Rick and his co-workers have made a new radioactive formula and a lot of bad guys are after them. So Rick wants to give his legacy to Morty before bad guys catch them.
There are n planets in their universe numbered from 1 to n. Rick is in planet number s (the earth) and he doesn't know where Morty is. As we all know, Rick owns a portal gun. With this gun he can open one-way portal from a planet he is in to any other planet (including that planet). But there are limits on this gun because he's still using its free trial.
![](https://i-blog.csdnimg.cn/blog_migrate/8a4f67a41d8b174b04e6b7a6c085ce1c.png)
By default he can not open any portal by this gun. There are q plans in the website that sells these guns. Every time you purchase a plan you can only use it once but you can purchase it again if you want to use it more.
Plans on the website have three types:
- With a plan of this type you can open a portal from planet v to planet u.
- With a plan of this type you can open a portal from planet v to any planet with index in range [l, r].
- With a plan of this type you can open a portal from any planet with index in range [l, r] to planet v.
Rick doesn't known where Morty is, but Unity is going to inform him and he wants to be prepared for when he finds and start his journey immediately. So for each planet (including earth itself) he wants to know the minimum amount of money he needs to get from earth to that planet.
The first line of input contains three integers n, q and s (1 ≤ n, q ≤ 105, 1 ≤ s ≤ n) — number of planets, number of plans and index of earth respectively.
The next q lines contain the plans. Each line starts with a number t, type of that plan (1 ≤ t ≤ 3). If t = 1 then it is followed by three integers v, u and w where w is the cost of that plan (1 ≤ v, u ≤ n, 1 ≤ w ≤ 109). Otherwise it is followed by four integers v, l, r and w where w is the cost of that plan (1 ≤ v ≤ n, 1 ≤ l ≤ r ≤ n, 1 ≤ w ≤ 109).
In the first and only line of output print n integers separated by spaces. i-th of them should be minimum money to get from earth to i-th planet, or - 1 if it's impossible to get to that planet.
3 5 1
2 3 2 3 17
2 3 2 2 16
2 2 2 3 3
3 3 1 1 12
1 3 3 17
0 28 12
4 3 1
3 4 1 3 12
2 2 3 4 10
1 2 4 16
0 -1 -1 12
In the first sample testcase, Rick can purchase 4th plan once and then 2nd plan in order to get to get to planet number 2.
深受启发的一道题,线段树维护的过程中即可完成dijkstra算法中priority_queue的任务,可以很大程度上提高效率。(此代码在Div2的提交中效率暂排第一)
具体每一步的解释都写在了代码中。
1 #include<cstdio> 2 #include <iostream> 3 #include <vector> 4 #include <algorithm> 5 typedef long long ll; 6 typedef unsigned long long ull; 7 #define pii pair <int, int> 8 #define pll pair <ll, ll> 9 #define mp make_pair 10 using namespace std; 11 const int MAX=1e5+5; 12 const ll INF=(ll)1e18;//dij中初始化使用的INF值 13 int n,q,s; 14 vector <pii>yi[MAX];//储存第一种 15 vector <pair<pii,int> >er[MAX],san[MAX];//储存第二种、第三种 16 vector <pii>now; 17 int opt; 18 int v,u,l,r,w;//对应记录时的各个值 19 ll d[MAX];//最短路中的d数组 20 ll lazy[MAX<<2];//懒惰标记 21 pair<ll,int> que[MAX<<2];//dijkstra中的优先队列,这里采用线段树就不再需要通过priority_queue维护,直接线段树维护即可 22 int tree[MAX<<2]; 23 /* 24 对编号为k的点进行“赋”x 25 */ 26 void sets(int k,ll x) 27 { 28 if(que[k].first==INF+1) 29 return; 30 que[k].first=min(que[k].first,x);//更新值 31 if(lazy[k]==-1) 32 lazy[k]=x; 33 else 34 lazy[k]=min(x,lazy[k]); 35 } 36 /* 37 将懒惰值下传 38 */ 39 void pushdown(int k) 40 { 41 if(lazy[k]!=-1) 42 { 43 sets(2*k,lazy[k]); 44 sets(2*k+1,lazy[k]); 45 lazy[k]=-1; 46 } 47 } 48 /* 49 将tree范围刷新 50 */ 51 void re(int k,int l,int r,int x) 52 { 53 if(l>x||tree[k]<x) 54 return; 55 if(l==r) 56 { 57 while(!san[l].empty()&&san[l].back().first.first>=x) 58 { 59 now.push_back(mp(san[l].back().first.second,san[l].back().second)); 60 san[l].pop_back(); 61 } 62 if(san[l].empty()) 63 tree[k]=-1; 64 else 65 tree[k]=san[l].back().first.first; 66 return; 67 } 68 int mid=l+r>>1; 69 re(2*k,l,mid,x);re(2*k+1,mid+1,r,x); 70 tree[k]=max(tree[2*k],tree[2*k+1]); 71 } 72 /* 73 更新函数.将[ul,ur]“更新”为x 74 */ 75 void update(int ul,int ur,int l,int r,int k,ll x) 76 { 77 if(ul==l&&ur==r) 78 { 79 sets(k,x);return; 80 } 81 else 82 { 83 pushdown(k); 84 int mid=l+r>>1; 85 if(ur<=mid) 86 update(ul,ur,l,mid,2*k,x); 87 else if(ul>mid) 88 update(ul,ur,mid+1,r,2*k+1,x); 89 else 90 { 91 update(ul,mid,l,mid,2*k,x);update(mid+1,ur,mid+1,r,2*k+1,x); 92 } 93 que[k]=min(que[2*k],que[2*k+1]); 94 } 95 } 96 //void upd(int k,int l,int r,int x) 97 //{ 98 // if(l==r) 99 // 100 //} 101 /* 102 "终止“函数,将指定位置赋值为INF+1,使其在接下来的操作不再进行 103 */ 104 void stop(int l,int r,int k,int lo) 105 { 106 if(l==r) 107 que[k]=mp(INF+1,l); 108 else 109 { 110 pushdown(k); 111 int mid=l+r>>1; 112 if(lo<=mid) 113 stop(l,mid,2*k,lo); 114 else 115 stop(mid+1,r,2*k+1,lo); 116 que[k]=min(que[2*k],que[2*k+1]); 117 } 118 119 } 120 /* 121 初始建树,只考虑第三种情况的区间大小 122 tree维护区间内每点为第三种情况起点时所有对应区间右侧的最大值的最大值 123 */ 124 void build(int k,int l,int r) 125 { 126 lazy[k]=-1; 127 if(l==r) 128 { 129 que[k]=mp(INF,l); 130 if(!san[l].empty())//如果存在以此点为起点的第三种情况区间 131 { 132 tree[k]=san[l].back().first.first;//之前已经排好序,取最长的右端作为此叶子结点值即可 133 } 134 else 135 tree[k]=-1;//不然不存在这样的区间,赋值为-1 136 return; 137 } 138 int mid=l+r>>1; 139 build(2*k,l,mid); 140 build(2*k+1,mid+1,r); 141 tree[k]=max(tree[2*k],tree[2*k+1]); 142 que[k]=min(que[2*k],que[2*k+1]); 143 } 144 145 void dijkstra(int s)//从s点开始进行dij算法求最短路 146 { 147 fill(d+1,d+n+1,INF); 148 update(s,s,1,n,1,0); 149 while(1) 150 { 151 int v=que[1].second; 152 ll zhi=que[1].first; 153 if(zhi==INF+1) 154 break; 155 d[v]=zhi; 156 stop(1,n,1,v); 157 for(int i=0;i<(int)yi[v].size();i++) 158 { 159 int u=yi[v][i].first,w=yi[v][i].second; 160 update(u,u,1,n,1,d[v]+w);//dij中的操作 161 } 162 for(int i=0;i<(int)er[v].size();i++) 163 { 164 int l=er[v][i].first.first,r=er[v][i].first.second,w=er[v][i].second; 165 update(l,r,1,n,1,d[v]+w); 166 } 167 now.clear(); 168 re(1,1,n,v); 169 for(int i=0;i<(int)now.size();i++) 170 { 171 int u = now[i].first; 172 int w = now[i].second; 173 update(u,u,1,n,1,w+d[v]); 174 } 175 } 176 } 177 int main() 178 { 179 scanf("%d%d%d",&n,&q,&s); 180 while(q--) 181 { 182 scanf("%d",&opt); 183 if(opt==1) 184 { 185 scanf("%d%d%d",&v,&u,&w); 186 yi[v].push_back(mp(u,w)); 187 } 188 else 189 { 190 scanf("%d%d%d%d",&v,&l,&r,&w); 191 if(opt==2) 192 er[v].push_back(mp(mp(l,r),w)); 193 else 194 san[l].push_back(mp(mp(r,v),w)); 195 } 196 } 197 for(int i=1;i<=n;i++) 198 sort(san[i].begin(),san[i].end()); 199 build(1,1,n); 200 dijkstra(s); 201 for (int i = 1; i <= n; i++) { 202 if (d[i] == INF) { 203 printf("-1 "); 204 } else 205 { 206 printf("%I64d ",d[i]); 207 } 208 } 209 return 0; 210 }
Rick and his co-workers have made a new radioactive formula and a lot of bad guys are after them. So Rick wants to give his legacy to Morty before bad guys catch them.
There are n planets in their universe numbered from 1 to n. Rick is in planet number s (the earth) and he doesn't know where Morty is. As we all know, Rick owns a portal gun. With this gun he can open one-way portal from a planet he is in to any other planet (including that planet). But there are limits on this gun because he's still using its free trial.
![](https://i-blog.csdnimg.cn/blog_migrate/8a4f67a41d8b174b04e6b7a6c085ce1c.png)
By default he can not open any portal by this gun. There are q plans in the website that sells these guns. Every time you purchase a plan you can only use it once but you can purchase it again if you want to use it more.
Plans on the website have three types:
- With a plan of this type you can open a portal from planet v to planet u.
- With a plan of this type you can open a portal from planet v to any planet with index in range [l, r].
- With a plan of this type you can open a portal from any planet with index in range [l, r] to planet v.
Rick doesn't known where Morty is, but Unity is going to inform him and he wants to be prepared for when he finds and start his journey immediately. So for each planet (including earth itself) he wants to know the minimum amount of money he needs to get from earth to that planet.
The first line of input contains three integers n, q and s (1 ≤ n, q ≤ 105, 1 ≤ s ≤ n) — number of planets, number of plans and index of earth respectively.
The next q lines contain the plans. Each line starts with a number t, type of that plan (1 ≤ t ≤ 3). If t = 1 then it is followed by three integers v, u and w where w is the cost of that plan (1 ≤ v, u ≤ n, 1 ≤ w ≤ 109). Otherwise it is followed by four integers v, l, r and w where w is the cost of that plan (1 ≤ v ≤ n, 1 ≤ l ≤ r ≤ n, 1 ≤ w ≤ 109).
In the first and only line of output print n integers separated by spaces. i-th of them should be minimum money to get from earth to i-th planet, or - 1 if it's impossible to get to that planet.
3 5 1
2 3 2 3 17
2 3 2 2 16
2 2 2 3 3
3 3 1 1 12
1 3 3 17
0 28 12
4 3 1
3 4 1 3 12
2 2 3 4 10
1 2 4 16
0 -1 -1 12
In the first sample testcase, Rick can purchase 4th plan once and then 2nd plan in order to get to get to planet number 2.