题解:P15805 [GESP202603 八级] 子图最短路
Lele_Programmer · · 题解
P15805 题解
思路
看到 考虑乱搞。
选择判断题里面有一道启发了我们:用 dijkstra 跑完一张图的最短路,再用 floyd 跑一遍,不会影响答案正确性。
所以我们先枚举
发现模数是
枚举左右端点都是
代码
由于我的代码包含过多火车头,所以这里只提供关键部分,反正应该能看懂,但是你抄不走。
#define _rep(i,a,b) for (int i=(a);i<=(b);++i)
#define _graph(i,u) for (int i=h[u];~i;i=ne[i])
typedef pair<int,int> pii;
using namespace IO;
using namespace Graph;
int n,m,ans;
int G[N][N];
int g[N][N];
int dis[N];
bool flag[N];
priority_queue<pii,vector<pii>,greater<pii>> q;
inline void dijkstra(int s) {
_rep(i,1,n) dis[i]=mod,flag[i]=0;
q.emplace(pii{dis[s]=0,s});
while (!q.empty()) {
auto tp=q.top(); q.pop();
int u=tp.second;
if (flag[u]) continue;
flag[u]=true;
_graph(i,u) if (dis[e[i]]>dis[u]+w[i] && !flag[e[i]]) q.emplace(pii{dis[e[i]]=dis[u]+w[i],e[i]});
}
}
int main() {
Graph::init_graph();
read(n,m);
_rep(i,1,n) _rep(j,1,n) G[i][j]=mod;
_rep(i,1,n) G[i][i]=0;
while (m--) {
int a,b,c;
read(a,b,c);
G[a][b]=G[b][a]=min(G[a][b],c);
}
_rep(l,1,n) {
_rep(i,1,n) _rep(j,1,n) g[i][j]=mod;
_rep(r,l,n) {
if (l==r) Graph::restore_graph(n);
_rep(t,l,r) if (G[r][t]!=inf) add(r,t,G[r][t]),add(t,r,G[r][t]);
dijkstra(r);
_rep(i,l,r) _rep(j,l,r) {
chmin(g[i][j],dis[i]+dis[j]);
if (i<j) ans=(ans+g[i][j])%mod;
}
}
}
write(ans);
return 0;
}