题目背景
小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
题目即求缩点后从1到达n的最短距离
缩点后并不需要重新建边,只需要在跑最短路时判断u,v两点是否在同一个强连通分量中。
若在同一个强联通分量中,那么直接将边权赋值为0。
#include<complex> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int N=2e5+7; struct node{ int v,w,nxt; }e[N*5]; int n,m,Enum,cnt,top; int front[N],Low[N],Dfn[N],fat[N],dis[N],sk[N]; bool vis[N]; queue<int>q; int qread() { int x=0; char ch=getchar(); while(ch<‘0‘ || ch>‘9‘)ch=getchar(); while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x; } void Insert(int u,int v,int w) { e[++Enum].v=v; e[Enum].w=w; e[Enum].nxt=front[u]; front[u]=Enum; } int find(int x) { if(fat[x]!=x)fat[x]=find(fat[x]); return fat[x]; } void Tarjan(int x) { Low[x]=Dfn[x]=++cnt; vis[x]=1; sk[++top]=x; int v; for(int i=front[x];i;i=e[i].nxt) { v=e[i].v; if(!Dfn[v]) { Tarjan(v); Low[x]=min(Low[x],Low[v]); } else if(vis[v]) Low[x]=min(Low[x],Dfn[v]); } if(Low[x]==Dfn[x]) do{ fat[sk[top]]=x; vis[sk[top--]]=0; }while(sk[top+1]!=x); } void SPFA() { memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[1]=0; vis[1]=1; q.push(1); int u,v,r1,r2; while(!q.empty()) { u=q.front();r1=find(u); q.pop(); vis[u]=0; for(int i=front[u];i;i=e[i].nxt) { v=e[i].v;r2=find(v); if(r1==r2)e[i].w=0; if(dis[v]>dis[u]+e[i].w) { dis[v]=dis[u]+e[i].w; if(!vis[v]) { vis[v]=1; q.push(v); } } } } } int main() { scanf("%d%d",&n,&m); int u,v,w; for(int i=1;i<=m;i++) { u=qread();v=qread();w=qread(); Insert(u,v,w); } for(int i=1;i<=n;i++) if(!Dfn[i]) Tarjan(i); SPFA(); printf("%d\n",dis[n]); return 0; }
原文地址:https://www.cnblogs.com/1078713946t/p/8284453.html
时间: 2024-10-03 15:24:11