题目链接
由题意可以知道双向道路没有负边权,而单向负权路不构成环。如果把所有的道路单独添加到图里,会形成若干个连通块。把每个连通块看做一个点,把航线添加进图里,会形成DAG。可以在DAG上跑拓扑序,在线性时间里求出单元最短路。在每个连通块内部用堆优化的dijkstra。
步骤:
1.将所有道路添加到图中形成若干连通块,遍历每一个连通块记录每个节点所属的连通块编号(并查集);
2.将有向边添加到图中,统计每个连通块的总入度,将入度为0的连通块添加到队列中;
3.取出连通块跑dijkstra,扫描连通块内部外部的所有边,扫描到连通块外部的边入度减一,入度为0时插入拓扑序队列中;
最终最短路数组即为所求,时间复杂度O(t+p+rlogt);
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
#define _rep(i,a,b) for(int i=(a);i<=(b);i++)
#define _for(i,a,b) for(int i=(a);i<(b);i++)
#define PB(v) push_back(v)
#define INF 0x3f3f3f3f
const int N=25010;
const int M=5e4+10;
int t,r,p,s;
int fa[N];
struct Edge{
int v,w,nx;
}edge[M<<2]