华山论剑
题目描述
话说数年一度的武林盛事“华山论剑”将至,东邪、西毒、南帝、北丐,老顽童等高手云集华山之巅,誓要分出究竟谁是武林至尊……
如此武林盛世,当然求围观。据统计,有n-1位同学想去华山看热闹,他们分别住在编号为1-n(除华山所在地x)的地方,华山编号为x(1<=x<=n)。现在有M(1<=m<=100000)条有向道路,每条路长为ti(1<=ti<=100)。
由于每位同学看完打架后还要回家吃饭,所以要选择最短路径,求这n-1位同学的最短路径(一个来回)中最长的一条的长度。
特别提醒:可能有权值不同的重边。
数据保证每位同学均能到达华山处,并从华山返回。
如此武林盛世,当然求围观。据统计,有n-1位同学想去华山看热闹,他们分别住在编号为1-n(除华山所在地x)的地方,华山编号为x(1<=x<=n)。现在有M(1<=m<=100000)条有向道路,每条路长为ti(1<=ti<=100)。
由于每位同学看完打架后还要回家吃饭,所以要选择最短路径,求这n-1位同学的最短路径(一个来回)中最长的一条的长度。
特别提醒:可能有权值不同的重边。
数据保证每位同学均能到达华山处,并从华山返回。
输入
第1行: n,m,x;
第2~m+1行: ai,bi,ti,表示有一条从ai到bi的路,长度为ti.
第2~m+1行: ai,bi,ti,表示有一条从ai到bi的路,长度为ti.
输出
输出仅一行,为最长最短路的长度。
样例输入
4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3
样例输出
10
提示
对于60%的数据,满足 1<=n<=100
对于100%的数据,满足 1<=n<=1000。
对于100%的数据,满足 1<=n<=1000。
分析:
并不难的最短路。
分别正反向建边,然后正反跑两次最短路,再求两次最短路之和的最大值就行了。
Code:
//It is made by HolseLee on 17th Aug 2018 //华山论剑 #include<bits/stdc++.h> #define Max(a,b) (a)>(b)?(a):(b) using namespace std; const int N=1001; const int M=1e5+7; int n,m,tag,h1[N],h2[N],cnt1,cnt2,dis1[N],dis2[N],ans; bool vis[N]; struct Node{ int to,val,nxt; }e1[M],e2[M]; queue<int>t; inline int read() { char ch=getchar();int num=0;bool flag=false; while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();} while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();} return flag?-num:num; } inline void add1(int x,int y,int z) { e1[++cnt1].to=y; e1[cnt1].val=z; e1[cnt1].nxt=h1[x]; h1[x]=cnt1; } inline void add2(int x,int y,int z) { e2[++cnt2].to=y; e2[cnt2].val=z; e2[cnt2].nxt=h2[x]; h2[x]=cnt2; } void spfa1() { memset(vis,0,sizeof(vis)); memset(dis1,0x7f,sizeof(dis1)); while(!t.empty())t.pop(); dis1[tag]=0;vis[tag]=1; t.push(tag); int x,y; while(!t.empty()){ x=t.front();t.pop(); vis[x]=0; for(int i=h1[x];i!=-1;i=e1[i].nxt){ y=e1[i].to; if(dis1[y]>dis1[x]+e1[i].val){ dis1[y]=dis1[x]+e1[i].val; if(!vis[y])t.push(y),vis[y]=1; } } } } void spfa2() { memset(vis,0,sizeof(vis)); memset(dis2,0x7f,sizeof(dis2)); while(!t.empty())t.pop(); dis2[tag]=0;vis[tag]=1; t.push(tag); int x,y; while(!t.empty()){ x=t.front();t.pop(); vis[x]=0; for(int i=h2[x];i!=-1;i=e2[i].nxt){ y=e2[i].to; if(dis2[y]>dis2[x]+e2[i].val){ dis2[y]=dis2[x]+e2[i].val; if(!vis[y])t.push(y),vis[y]=1; } } } } int main() { n=read();m=read();tag=read(); memset(h1,-1,sizeof(h1)); memset(h2,-1,sizeof(h2)); int x,y,z; for(int i=1;i<=m;++i){ x=read();y=read();z=read(); add1(x,y,z);add2(y,x,z); } spfa1();spfa2(); for(int i=1;i<=n;++i){ ans=Max(ans,dis1[i]+dis2[i]); } printf("%d ",ans); return 0; }