【最短路算法】聚会
一、题号605
题目描述:小 S 想要从某地出发去同学的家中参加一个 party,但要有去有回。他想让所用的时间尽量的短。但他又想知道从不同的点出发, 来回的最短时间中最长的时间是多少,这个任务就交给了你。
输入格式:第一行三个正整数n,m,k(n是节点个数,m是有向边的条数,k是参加聚会的)地点编号(1<=n<=1000,1<=m<=100,000)
输出格式:一个整数,为不同的节点出发的最短时间中最长的时间。
样例输入:
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
二、思路分析:题意的意思是给定一有向图G(V,E)分别求所有点到一点k的最短路径与k到所有点的最短路径
那么我们新建一个图,将原图的所有边反向,(所有点->k)就转换为了 (k->所有点)
接下来这道题就是板子了分别对新旧图都跑一遍Dijs算法就行了
三、Solution:
#include<bits/stdc++.h>
#define MAX 2000
#define Inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int> PII;
struct Edge
{
int to,w;
};
int n,m,k;
int dis1[MAX],dis2[MAX];
vector<Edge> G[MAX];
vector<Edge> opG[MAX];
void AddG(int from,int to,int w)
{
G[from].push_back({to,w});
opG[to].push_back({from,w});
}
void read()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
AddG(x,y,z);
}
}
void Dijs1(int s)
{
bool vis[MAX];
memset(dis1,0x3f3f3f3f,sizeof(dis1));
memset(vis,0,sizeof(vis));
priority_queue<PII,vector<PII>,greater<PII> >heap;
dis1[s]=0;
heap.push({0,s});
while(!heap.empty())
{
int x=heap.top().second;
heap.pop();
if(vis[x]) continue;
vis[x]=1;
for(int i=0;i<int(G[x].size());i++)
{
int y=G[x][i].to;
int w=G[x][i].w;
if(dis1[y]>dis1[x]+w)
{
dis1[y]=dis1[x]+w;
heap.push({dis1[y],y});
}
}
}
}
void Dijs2(int s)
{
bool vis[MAX];
memset(dis2,0x3f3f3f3f,sizeof(dis2));
memset(vis,0,sizeof(vis));
priority_queue<PII,vector<PII>,greater<PII> >heap;
dis2[s]=0;
heap.push({0,s});
while(!heap.empty())
{
int x=heap.top().second;
heap.pop();
if(vis[x]) continue;
vis[x]=1;
for(int i=0;i<int(opG[x].size());i++)
{
int y=opG[x][i].to;
int w=opG[x][i].w;
if(dis2[y]>dis2[x]+w)
{
dis2[y]=dis2[x]+w;
heap.push({dis2[y],y});
}
}
}
}
int main()
{
read();
Dijs1(k);
Dijs2(k);
int ans=0;
for(int i=1;i<=n;i++)
{
if(dis1[i]==Inf) dis1[i]=0;
// printf("%d ",dis1[i]);
if(dis2[i]==Inf) dis2[i]=0;
// printf("%d ",dis2[i]);
}
for(int i=1;i<=n;i++) ans=max(ans,dis1[i]+dis2[i]);
printf("%d",ans);
}

浙公网安备 33010602011771号