HDU 6714 最短路2(Dijkstra)

HDU 6714 最短路2(Dijkstra)

题面

题意:

对于$floyed$算法,$D_{i,j}$表示最外层循环最小的能够求出来$dis_{i,j}$的循环次数,计算$\sum_{i=1}^{n}{\sum_{j=1}^{n}{D_{i,j}}}$

思路

其实$D_{i,j}$即为$i$到$j$的最短路路径上最小的不包含$i,j$的最大下标。我们跑$n$次$Dijkstra$,每次更新路径上的最小的最大下标即可。复杂度$O(n^2log(n))$。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
inline bool read(ll &num) {
char in;bool IsN=false;
in=getchar();
if(in==EOF) return false;
while(in!='-'&&(in<'0'||in>'9')) in=getchar();
if(in=='-'){ IsN=true;num=0;}
else num=in-'0';
while(in=getchar(),in>='0'&&in<='9'){
num*=10,num+=in-'0';
}
if(IsN) num=-num;
return true;
}
const ll N = 3005;
vector<pair<ll,ll> > G[N];
struct node{
ll id;
ll DIS;
};
ll dis[N],n,m,u,v,w,pre[N],mx[N];
bool vis[N];
bool operator<(node a,node b){
return a.DIS>b.DIS;
}
ll dij(ll st){
priority_queue<node> q;
memset(vis,0,sizeof(vis));
for(ll i=1;i<=n;i++) dis[i]=999999999999999;
for(ll i=1;i<=n;i++) pre[i]=999999999999999;
for(ll i=1;i<=n;i++) mx[i]=0;
dis[st]=0;
q.push({st,0});
while(!q.empty()){
node rt=q.top();q.pop();
ll u=rt.id;
if(vis[u]) continue;
vis[u]=1;
for(auto V:G[u]){
ll v=V.first;
ll w=V.second;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
q.push({v,dis[v]});
mx[v]=max(mx[u],u);
}
else if(dis[v]==dis[u]+w){
mx[v]=min(mx[v],max(mx[u],u));
}
if(u==st) mx[v]=0;
}
}
ll res=0;
for(int i=1;i<=n;i++) res+=mx[i];
return res;
}
int main(){
ll T;
read(T);
while(T--){
read(n);read(m);
for(int i=1;i<=n;i++) G[i].clear();
for(ll i=1;i<=m;i++){
read(u);read(v);read(w);
G[u].push_back({v,w});
G[v].push_back({u,w});

} ll ans=0;
for(ll i=1;i<=n;i++){
ans+=dij(i);
}
printf("%lld\n",ans%998244353);
}
return 0;
}