火炬传递 题解
公约
-
E.u,E.v,E.w
题目
火炬传递
题目描述
对于
思路
由暴力到正解
我们撕开一个环,发现:一个环就是一条边加上一条更长的边。
所以我们思考:
对于每一条边
求答案:
那怎么快速全源最短路呢?
以每个点为源点分别跑一次 Dijkstra 。
总时间复杂度:
下面是 \mathbf{Coding} 和 \mathbf{Typing} (\mathbf{copying} )时间!
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e3+10;
const int MAXM = 1e4+10;
const int INF = 0x3f3f3f3f;
//Grath
int n,m,x,y,z,ans = INF;
struct edge{
int to,w;
};
vector<edge> v[MAXN];
//Dijkstra
int dis[MAXN][MAXN];
bool vis[MAXN][MAXN];
bool operator < (const edge &b,const edge &a){
return a.w<b.w;
}
priority_queue<edge> pq;
void dijkstra(int s){
dis[s][s] = 0;
pq.push({s,0});
while(!pq.empty()){
auto x = pq.top();
pq.pop();
if(vis[s][x.to]) continue;
vis[s][x.to] = true;
for(auto i:v[x.to]){
if(dis[s][i.to]>dis[s][x.to]+i.w){
dis[s][i.to] = dis[s][x.to]+i.w;
pq.push({i.to,dis[s][i.to]});
}
}
}
}
signed main(){
memset(dis,0x3f,sizeof(dis));
scanf("%d%d",&n,&m);
for(int i = 1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
v[x].push_back({y,z});
}
for(int i = 1;i<=n;i++) dijkstra(i);
for(int i = 1;i<=n;i++){
for(auto j:v[i]){
ans = min(ans,j.w+dis[j.to][i]);
}
}
printf("%d",ans);
return 0;
}