题目大意:有编号为1-N的牛,它们之间存在一些单向的路径。给定一头牛的编号,其他牛要去拜访它并且拜访完之后要返回自己原来的位置,求这些牛中所花的最长的来回时间是多少(最短的最长)?
解题思路:一开始以为最短路没有难题,抱着水水的心态来做这个专题,没想到立刻就给我颜色看了。
这道题我没有多想,拿到题目我就准备dijsktra套模板,从X做一次单源最短路(无终点),然后再从1~N(X除外)做一次单源最短路(有终点,遇到X停止),然后把来回和不断与全局变量ans比较,最后得到结果。方法无误,但是时间复杂度我就呵呵了。
然后我自以为脑洞大开,想到全源最短路Folyd。好吧,直接全源,然后将dis[x][i]+dis[i][x]与ans比较,最后得出结果。然后,考虑时间复杂度,我也呵呵了。
最后TLE了好久,没忍住,才去看了题解。看完第一句话我就傻了,先从X开始做一次单源最短路,这是去所花的最短时间。然后因为这是个有向图,把边的方向换一下,再做一次从X开始的单源最短路,这就是回所花的最短时间。两组数据加起来,与全局变量ans比较,最后得出结果。对比时间复杂度,这种方法的时间复杂度是常数级的dijsktra。唉,淡淡的忧桑,我的ACM还有希望吗~~~
代码:因为本人的代码能力实在有限,所以就不搞什么高大上了,直接dijsktra复制一遍上,求轻喷
#include <set>
#include <map>
#include <list>
#include <queue>
#include <stack>
#include <cmath>
#include <string>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define PB push_back
#define FOR(i,n,m) for(int i=n;i<=m;i++)
#define ROF(i,n,m) for(int i=n;i>=m;i--)
#define clr(i,j) memset(i,j,sizeof(i))
#define maxn 1005
typedef long long ll;
typedef pair<int,int> pii;
const int inf = 0x3f3f3f3f;
int n;
struct edge
{
int to,dis;
} t;
vector<edge>p[maxn];
vector<edge>q[maxn];
bool vis[maxn];
int dis[maxn];
int dic[maxn];
int dijsktra(int s,int e)
{
clr(vis,false);
clr(dis,inf);
dis[s]=0;
while(1)
{
int x=0,mi=inf;
for(int i=1; i<=n; i++)
if(!vis[i]&&dis[i]<mi)
{
x=i;
mi=dis[i];
}
if(x==0) return-1;
if(x==e) return dis[e];
vis[x]=true;
for(int i=0; i<p[x].size(); i++)
{
int y=p[x][i].to,xy=p[x][i].dis;
if(!vis[y]&&dis[y]>dis[x]+xy)
dis[y]=dis[x]+xy;
}
}
}
int dijsktra1(int s,int e)
{
clr(vis,false);
clr(dic,inf);
dic[s]=0;
while(1)
{
int x=0,mi=inf;
for(int i=1; i<=n; i++)
if(!vis[i]&&dic[i]<mi)
{
x=i;
mi=dic[i];
}
if(x==0)return-1;
if(x==e)return dic[e];
vis[x]=true;
for(int i=0; i<q[x].size(); i++)
{
int y=q[x][i].to,xy=q[x][i].dis;
if(!vis[y]&&dic[y]>dic[x]+xy)
dic[y]=dic[x]+xy;
}
}
}
int main()
{
int m,x;
while(~scanf("%d %d %d",&n,&m,&x))
{
for(int i=1; i<=n; i++)
p[i].clear(),q[i].clear();
while(m--)
{
int a,b;
scanf("%d %d %d",&a,&b,&t.dis);
t.to=b;
p[a].PB(t);
t.to=a;
q[b].PB(t);
}
dijsktra(x,0);
dijsktra1(x,0);
int ans=0;
for(int i=1; i<=n; i++)
if(dis[i]!=inf&&dic[i]!=inf)
ans=max(ans,dis[i]+dic[i]);
printf("%d\n",ans);
}
return 0;
}