思路:
- 正权,有向图,从每个点走到终点再返回是一条路,找所有N-1条路(N个点)中的最大值。
- 自然想到可用Floyd-Warshall,也不出意料TLE。
- 在Marvis code的BLOG找到正解:将每个点到定点的路径反向,转化为单源点到全图。此操作通过邻接矩阵的转置来实现。
注意:
- 多源点单终点类问题:通过对 mp[i][j] 进行矩阵转置解题。注意具体i,j的操作(如果 j 从 1 开始,相当于转置了两次)。
for(int i=1;i<=N;i++){
for(int j=i+1;j<=N;j++){
int temp = mp[i][j];
mp[i][j] = mp[j][i];
mp[j][i] = temp;
}
}
- 数组作为参数传递有两种方法:int dis[],或者 int * dis。
- 数组作为参数传递时,函数中 sizeof(dis) == 1,为防止错误,尽量不在子函数中使用 memset。
代码:
#include <iostream>
#include <algorithm>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1005;
int mp[maxn][maxn];
int N,M,X;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>N>>M>>X;
memset(mp,INF,sizeof(mp));
for(int i=1;i<maxn;i++){
mp[i][i] = 0;
}
for(int i=1;i<=M;i++){
int A,B,T;
cin>>A>>B>>T;
mp[A][B] = min(mp[A][B] , T);
}
for(int k=1;k<=N;k++)
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
mp[i][j] = min(mp[i][k] + mp[k][j] , mp[i][j]);
int ans = 0;
for(int i=1;i<=N;i++){
if(mp[i][X] == INF || mp[X][i] == INF)
continue;
ans = max(ans , mp[i][X] + mp[X][i]);
}
cout<<ans<<endl;
return 0;
}
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1005;
int mp[maxn][maxn];
int dis_back[maxn];
int dis_go[maxn];
bool vis[maxn];
int N,M,X;
int ans=0;
struct node{
int id;
int dis;
node(int id,int dis) : id(id) , dis(dis) {} ;
friend bool operator > (const node & a,const node & b)
{
return a.dis > b.dis;
}
};
priority_queue<node , vector<node> , greater<node> > Q;
void IJK(int dis[]){
for(int i=1;i<maxn;i++)
dis[i] = INF;
memset(vis,0,sizeof(vis));
Q.push(node(X,0));dis[X] = 0;
while(Q.size()){
node cur = Q.top();Q.pop();
if(vis[cur.id])
continue;
vis[cur.id] = true;
for(int i=1;i<=N;i++){
if(vis[i])
continue;
if(dis[i] > dis[cur.id] + mp[cur.id][i]){
dis[i] = dis[cur.id] + mp[cur.id][i];
Q.push(node(i,dis[i]));
}
}
}
return ;
}
int main(){
cin>>N>>M>>X;
memset(mp,INF,sizeof(mp));
for(int i=0;i<maxn;i++)
mp[i][i] = 0;
for(int i=1;i<=M;i++){
int A,B,T;
cin>>A>>B>>T;
mp[A][B] = min(mp[A][B] , T);
}
IJK(dis_back);
for(int i=1;i<=N;i++){
for(int j=i+1;j<=N;j++){
int temp = mp[i][j];
mp[i][j] = mp[j][i];
mp[j][i] = temp;
}
}
IJK(dis_go);
for(int i=1;i<=N;i++){
if(dis_go[i] == INF || dis_back[i] == INF)
continue;
ans = max(ans , dis_go[i] + dis_back[i]);
}
cout<<ans<<endl;
return 0;
}