题目
思路
这道题相对来说比较简单,我用的是堆优化的dijkstra算法,就是用优先队列来代替了每次找最小路径的循环,减小了时间复杂度,这道题首先我们可以先计算每头牛从X点回自己的起点时的最短路,记录下来成一个数组,然后将邻接矩阵转置(邻接表的话就重新构造一个邻接表),这里的转置相当于将每条边的方向反过来,这样的话再计算一下每头牛从X点回自己的起点时的最短路,就相当于没调换边的方向时,每头牛从自己的起点出发到X的最短路,所以,就把两个求出来的数组对应求和,得到和数组,找其中的最大值就可以了,这里的转置技巧还是很常用的。
题解
#include <iostream>
#include <cstring>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=1000100;
struct qnode{
int v;
int c;
qnode(int _v=0,int _c=0):v(_v),c(_c){}
bool operator <(const qnode &r)const{
return c>r.c;
}
};
struct Edge{
int v,cost;
Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}
};
vector<Edge>E1[MAXN];
vector<Edge>E2[MAXN];
bool vis[MAXN];
int dist[MAXN];
//点的编号从 1 开始
void Dijkstra(int n,int start,vector<Edge>E[MAXN]){
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++)dist[i]=INF;
priority_queue<qnode>que;
while(!que.empty())que.pop();
dist[start]=0;
que.push(qnode(start,0));
qnode tmp;
while(!que.empty()){
tmp=que.top();
que.pop();
int u=tmp.v;
if(vis[u])continue;
vis[u]=true;
for(int i=0;i<E[u].size();i++){
int v=E[tmp.v][i].v;
int cost=E[u][i].cost;
if(!vis[v]&&dist[v]>dist[u]+cost){
dist[v]=dist[u]+cost;
que.push(qnode(v,dist[v]));
}
}
}
}
void addedge(int u,int v,int w,vector<Edge>E[MAXN]){
E[u].push_back(Edge(v,w));
}
int main()
{
int n,m,x;
cin>>n>>m>>x;
int lu1[n+1][n+1];
int lu2[n+1][n+1];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)
{
lu1[i][j]=0;
lu2[i][j]=0;
continue;
}
lu1[i][j]=-1;
lu2[i][j]=-1;
}
}
for(int i=0;i<m;i++)
{
int v,u,w;
cin>>v>>u>>w;
lu1[v][u]=w;
lu2[u][v]=w;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(lu1[i][j]!=0&&lu1[i][j]!=-1)
{
addedge(i,j,lu1[i][j],E1);
}
}
}
Dijkstra(n,x,E1);
int ans=0;
int max_n[n+1];
memset(max_n,0,sizeof(max_n));
for(int i=1;i<=n;i++)
{
max_n[i]=dist[i];
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(lu2[i][j]!=0&&lu2[i][j]!=-1)
{
addedge(i,j,lu2[i][j],E2);
}
}
}
Dijkstra(n,x,E2);
for(int i=1;i<=n;i++)
{
if(ans<max_n[i]+dist[i])
{
ans=max_n[i]+dist[i];
}
}
cout<<ans<<endl;
return 0;
}