1413: StarFarming [最短路]
时间限制: 1 Sec 内存限制: 128 MB提交: 429 解决: 68 统计
题目描述
星农(StarFarming)公司计划要给员工发路费津贴,发放的规则是这样的:1
到n-1
代表各个员工家的序号,n
代表公司。路费津贴只发给上班的最短路与回家的最短路的总路程最长的人。该市的路建造的有些奇怪,修路只修单行道,即只允许往某一个方向通行。
现在给你城市的有向图的地图,TLG请你帮忙计算谁能得到津贴,以及他上班和回家的总路程是多少。
输入
有多组测试数据。
每组第一行输入两个整数N
,M
。表示点的个数,与单行道的数量(可能有重复)
接下来m
行,每行输入三个整数x
,y
,z
。表示从x
到y
城市有一条单行道,距离为z
。
题目保证至少一人存在来回的路径。不存在的不发津贴(班都没法好好上还想要钱?!)
1≤N≤1000 1≤N≤1000
1≤M≤100000 1≤M≤100000
1≤x,y≤N 1≤x,y≤N
1≤z≤200 1≤z≤200
输出
对于每组数据,输出两个整数,分别表示获得津贴的人的序号以及总路程。(如果有多个人路程相同,取序号最小的)
样例输入
4 7
1 2 2
2 3 2
1 3 4
4 1 2
4 2 2
3 4 1
4 3 5
样例输出
1 7
提示
对于样例,
1
来回需要的最短路程是7
:1->2->3->4->1
2
来回需要的最短路程是5
:2->3->4->2
3
来回需要的最短路程是5
:3->4->2->3
所以输出1 7
来源
题意:》》》》
思路:这是一个单向图,所以主要的难点就是求上班的最短路,但是由于起点很多,所以一个一个求一定会超时,所以我们就要将图的方向反过来,有很多方法,譬如用优先队列,或者直接用两个矩阵储存(本弱鸡就是QAQ),然后写两个dijkstra函数,分别相加求出最大值即可,注意不能用sort(弱鸡因为这有WA了几发QAQ),因为sort是不稳定排序。貌似有这样的题。。。还有就是有的人可能不存在回路,所以要排除掉
下面附上代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#define inf 0x3f3f3f3f
using namespace std;
int matrix[1005][1005],matrix1[1005][1005],vis[1005],dis[1005];
int n,m,x,y,z;
struct node
{
int k,len;
}s[1005];
bool cmp(node a,node b)
{
if(a.len!=b.len)
return a.len>b.len;
return a.k<b.k;
}
void dijkstra(int n)//回家的最短路
{
memset(vis,0,sizeof(vis));
memset(dis,inf,sizeof(dis));
for(int i=1;i<=n;i++)
dis[i]=matrix[n][i];
vis[n]=1;
dis[n]=0;
int tem,v;
for(int i=1;i<=n;i++)
{
tem=inf;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&dis[j]<tem)
{
tem=dis[j];
v=j;
}
}
vis[v]=1;
for(int k=1;k<=n;k++)
{
if(!vis[k]&&matrix[v][k]<inf)
dis[k]=min(dis[k],dis[v]+matrix[v][k]);
}
}
}
void dijkstra1(int n)//求上班的最短路
{
memset(vis,0,sizeof(vis));
memset(dis,inf,sizeof(dis));
for(int i=1;i<=n;i++)
dis[i]=matrix1[n][i];
vis[n]=1;
dis[n]=0;
int tem,v;
for(int i=1;i<=n;i++)
{
tem=inf;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&dis[j]<tem)
{
tem=dis[j];
v=j;
}
}
vis[v]=1;
for(int k=1;k<=n;k++)
{
if(!vis[k]&&matrix1[v][k]<inf)
dis[k]=min(dis[k],dis[v]+matrix1[v][k]);
}
}
}
int main()
{
int n,m;
while(~scanf("%d %d",&n,&m))
{
memset(dis,inf,sizeof(dis));
memset(matrix,inf,sizeof(matrix));
memset(matrix1,inf,sizeof(matrix1));
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&x,&y,&z);
matrix[x][y]=min(matrix[x][y],z);//防止重边
matrix1[y][x]=min(matrix1[y][x],z);
}
dijkstra(n);
for(int i=1;i<n;i++)
s[i].len=dis[i];
dijkstra1(n);
for(int i=1;i<n;i++)
{
s[i].len+=dis[i];
s[i].k=i;
}
int ans=0,anspos;
for(int i=1;i<n;i++)
{
if(s[i].len<inf){
ans=s[i].len;
anspos=i;
break;//找出第一个存在回路的点
}
}
for(int i=1;i<n;i++){
if(s[i].len<inf&&s[i].len>ans){
ans=s[i].len;
anspos=i;
}
}//比较得出最大值和序号
printf("%d %d\n",anspos,ans);
}
return 0;
}