道路とルート
題名
有向エッジと無向エッジがいくつかあり、ループがないことがわかっているので、開始点から他の点までの最短距離を見つけます。
データ範囲
カードspfa
アイデア(acwingを参照)
この質問はより大きな頭脳を持っていますが、より深い考えを持っています。ループがないため、無向エッジで接続された一部のポイントはブロックと見なすことができ、これらのブロックは有向エッジを介して有向グラフを形成します。つまり、ローカルは無向グラフであり、グローバルは有向グラフです。
次に、トポロジーによるソートがグローバルで行われ、ダイクストラがブロック内で行われます。アルゴリズムの手順は次のとおりです。
- 最初にすべての双方向の道路を入力し、次に同様の方法ですべての接続ブロックを見つけ、2つの配列を計算します。各接続点がどの接続ブロックに属しているか、各接続ブロックがどの点にあるかを示します。
- すべてのルートを入力し、同時に接続されている各ブロックの度数を数えます。
- 接続されている各ブロックをトポロジー順に一度に処理します。最初に、次数0で接続されているすべてのブロックの数をキューに追加します。
- 接続されたブロックの入札数がキューの先頭から取得されるたび
- このブロックのすべてのポイントをヒープに追加してから、ヒープのすべてのポイントでダイクストラのアルゴリズムを実行します。
- 毎回ヒープ内の距離が最小のポイントverを取り出します
- 次に、verのすべての近傍jをトラバースします。id[ver] == id [j]の場合、jを更新できる場合はjをヒープに挿入し、id [ver]!= id [j]の場合はidを追加します[j]この接続されたブロックの次数は1減少します。0に減少すると、トポロジー的にソートされたキューに挿入されます。
コード
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int N = 25010, M = 150010, inf = 0x3f3f3f3f;
typedef pair<int,int> pii;
int n,R,P,S;
int h[N], e[M], ne[M], w[M], idx;
int dist[N], id[N];
bool st[N];
int bin[N];
int bcnt;
vector<int> block[N];
queue<int> que;
void add(int a,int b,int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
}
void dfs(int u,int k)
{
block[k].push_back(u);
id[u] = bcnt;
for(int i=h[u];~i;i=ne[i]){
int j = e[i];
if(!id[j]){
dfs(j,k);
}
}
}
void dijkstra(int bid)
{
priority_queue<pii,vector<pii>,greater<pii>> heap;
for(auto u:block[bid]){
heap.push({
dist[u],u});
}
while(heap.size()){
auto t = heap.top();
heap.pop();
int ver = t.second, distance = t.first;
if(st[ver]) continue;
st[ver] = true;
for(int i=h[ver];~i;i=ne[i]){
int j = e[i];
if(id[j]!=id[ver]&&--bin[id[j]]==0) que.push(id[j]);
if(dist[j]>distance+w[i]){
dist[j] = distance + w[i];
if(id[j]==id[ver]){
heap.push({
dist[j],j});
}
}
}
}
}
void topsort()
{
memset(dist,0x3f,sizeof(dist));
dist[S] = 0;
for(int i=1;i<=bcnt;i++)
if(!bin[i])
que.push(i);
while(que.size()){
int t = que.front();
que.pop();
dijkstra(t);
}
}
int main()
{
cin >> n >> R >> P >> S;
memset(h,-1,sizeof(h));
while(R--){
int a,b,c;
cin >> a >> b >> c;
add(a,b,c), add(b,a,c);
}
for(int i=1;i<=n;i++)
if(!id[i])
{
bcnt ++;
dfs(i,bcnt);
}
while(P--){
int a,b,c;
cin >> a >> b >> c;
add(a,b,c);
bin[id[b]] ++;
}
topsort();
for(int i=1;i<=n;i++){
if(dist[i]>inf/2) cout << "NO PATH" << endl;
else cout << dist[i] << endl;
}
return 0;
}