生活随笔
收集整理的這篇文章主要介紹了
P6348 [PA2011]Journeys 线段树优化建图 区间连区间
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
傳送門
文章目錄
題意:
每次連接[a,b][a,b][a,b]與[c,d][c,d][c,d]之間所有點,讓后跑最短路。
思路:
比普通的優化建圖能簡單點,我們只需要加兩個虛點之間邊權為111,讓后讓某個點連接一個區間,另一個連接另一個區間即可。注意是雙向邊,所以區間交換一下再連一次就好啦。
最后求最短路的時候由于邊權只有0,10,10,1所以用01bfs01bfs01bfs即可。
注意答案是每行一個,CPeditorCP editorCPeditor用多了,都不會自己看了。
復雜度O(nlogn)O(nlogn)O(nlogn)。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
<int,int> PII
;const int N
=500000*10,M
=N
*2,mod
=1e9+7,INF
=0x3f3f3f3f;
const double eps
=1e-6;int n
,m
,s
,base
;
int e
[M
],ne
[M
],w
[M
],h
[N
],idx
;
int dis
[N
],leaf
[N
],tot
;
bool st
[N
];void add(int a
,int b
,int c
) {e
[idx
]=b
,w
[idx
]=c
,ne
[idx
]=h
[a
],h
[a
]=idx
++;
}void build(int u
,int l
,int r
) {if(l
==r
) {leaf
[l
]=u
;return;}int mid
=(l
+r
)>>1;add(u
,u
*2,0); add(u
,u
*2+1,0);add(u
*2+base
,u
+base
,0); add(u
*2+1+base
,u
+base
,0);build(u
<<1,l
,mid
); build(u
<<1|1,mid
+1,r
);
}void change(int u
,int l
,int r
,int ql
,int qr
,int st
,int w
,int op
) {if(ql
<=l
&&qr
>=r
) {if(!op
) add(st
,u
,0);else add(u
+4*n
,st
,0);return;}int mid
=(l
+r
)>>1;if(ql
<=mid
) change(u
<<1,l
,mid
,ql
,qr
,st
,w
,op
);if(qr
>mid
) change(u
<<1|1,mid
+1,r
,ql
,qr
,st
,w
,op
);
}void bfs() {deque
<int>q
; q
.push_front(leaf
[s
]);memset(dis
,0x3f,sizeof(dis
));dis
[leaf
[s
]]=0;while(q
.size()) {int u
=q
.front(); q
.pop_front();for(int i
=h
[u
];~i
;i
=ne
[i
]) {int j
=e
[i
];if(dis
[j
]>dis
[u
]+w
[i
]) {dis
[j
]=dis
[u
]+w
[i
];if(w
[i
]) q
.push_back(j
);else q
.push_front(j
);}}}for(int i
=1;i
<=n
;i
++) printf("%d\n",dis
[leaf
[i
]]);
}int main()
{
memset(h
,-1,sizeof(h
));scanf("%d%d%d",&n
,&m
,&s
);base
=n
*4; tot
=8*n
+1;build(1,1,n
); for(int i
=1;i
<=n
;i
++) add(leaf
[i
],leaf
[i
]+base
,0),add(leaf
[i
]+base
,leaf
[i
],0);for(int i
=1;i
<=m
;i
++) {int a
,b
,c
,d
; scanf("%d%d%d%d",&a
,&b
,&c
,&d
);change(1,1,n
,a
,b
,tot
,1,0);change(1,1,n
,c
,d
,tot
+1,1,1);add(tot
+1,tot
,1); tot
+=2;change(1,1,n
,c
,d
,tot
,1,0);change(1,1,n
,a
,b
,tot
+1,1,1);add(tot
+1,tot
,1); tot
+=2;}bfs();return 0;
}
總結
以上是生活随笔為你收集整理的P6348 [PA2011]Journeys 线段树优化建图 区间连区间的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。