题目背景
小Z童鞋一日意外的看到小X写了一个正则表达式的高级程序,这个正则表达式程序仅仅由字符“0”,“1”,“.”和“*”构成,但是他能够匹配出所有在OJ上都AC的程序的核心代码!小Z大为颇感好奇,于是他决定入侵小X的电脑上去获得这个正则表达式的高级程序。
题目描述
在Internet网络中的每台电脑并不是直接一对一连通的,而是某些电脑之间存在单向的网络连接,也就是说存在A到B的连接不一定存在B到A的连接,并且有些连接传输速度很快,有些则很慢,所以不同连接传输所花的时间是有大有小的。另外,如果存在A到B的连接的同时也存在B到A的连接的话,那么A和B实际上处于同一局域网内,可以通过本地传输,这样花费的传输时间为0。
现在小Z告诉你整个网络的构成情况,他希望知道从他的电脑(编号为1),到小X的电脑(编号为n)所需要的最短传输时间。
输入格式
第一行两个整数n, m, 表示有n台电脑,m个连接关系。
接下来m行,每行三个整数u,v,w;表示从电脑u到电脑v传输信息的时间为w。
输出格式
输出文件仅一行为最短传输时间。
输入输出样例
输入 #1复制
3 2
1 2 1
2 3 1
输出 #1复制
2
输入 #2复制
5 5
1 2 1
2 3 6
3 4 1
4 2 1
3 5 2
输出 #2复制
3
说明/提示
对于40%的数据,1<=n<=1000, 1<=m<=10000
对于70%的数据,1<=n<=5000, 1<=m<=100000
对于100%的数据,1<=n<=200000, 1<=m<=1000000
比较明显的缩点之后最短路。
所以我们直接缩点,然后对缩点之后的图跑最短路即可。
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=2e5+10,M=1e6+10;
int n,m,low[N],dfn[N],col[N],vis[N],co,cnt,a[M],b[M],c[M],d[N];
int head[N],nex[M],to[M],tot;
stack<int> st;
vector<int> v1[N],v2[N];
inline void add(int a,int b){
to[++tot]=b; nex[tot]=head[a]; head[a]=tot;
}
void tarjan(int x){
dfn[x]=low[x]=++cnt; st.push(x),vis[x]=1;
for(int i=head[x];i;i=nex[i]){
if(!dfn[to[i]]){
tarjan(to[i]); low[x]=min(low[x],low[to[i]]);
}else if(vis[to[i]]) low[x]=min(low[x],dfn[to[i]]);
}
if(dfn[x]==low[x]){
int u; co++;
do{
u=st.top(); st.pop(); col[u]=co; vis[u]=0;
}while(u!=x);
}
}
int dijkstra(int s,int t){
priority_queue<pair<int,int> > q; q.push({0,s});
int vis[N]={0}; memset(d,0x3f,sizeof d); d[s]=0;
while(q.size()){
int u=q.top().second; q.pop();
if(vis[u]) continue; vis[u]=1;
for(int i=0;i<v1[u].size();i++){
int v=v1[u][i],val=v2[u][i];
if(d[v]>d[u]+val){
d[v]=d[u]+val;
if(!vis[v]) q.push({-d[v],v});
}
}
}
return d[t];
}
signed main(){
cin>>n>>m;
for(int i=1;i<=m;i++)
scanf("%d %d %d",&a[i],&b[i],&c[i]),add(a[i],b[i]);
for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
for(int i=1;i<=m;i++){
if(col[a[i]]==col[b[i]]) continue;
v1[col[a[i]]].push_back(col[b[i]]); v2[col[a[i]]].push_back(c[i]);
}
cout<<dijkstra(col[1],col[n])<<endl;
return 0;
}