1. 这道题完美地需要我们将点权转成边权:
Bessie 需要去这么多城市,而每座城市他都要赚 D 美元。那我们为什么不直接将每条普通边的边权就设置成 D 呢?这两者之间是等价的呀·····
那对于飞行边来说,同理,飞行边需要花费 T 美元,而到一个城市又可以赚 D 美元,那我们就可以将飞行边权设为 D−T。
这样,存图的事就解决了。
2. 只要你读懂题目,就会发现这题压根不是最短路,是最长路······
做最长路主要有两种做法
2.1 做最短路是我们是现将 dis 数组设为无穷大,再每次更新最小值。反过来,最长路就可以将 dis 数组都设为 0 ,再每次更新最大值。
2.2 将所有边权都取反后,再求最短路(spfa处理负权边)
3:相同的与不同点
相同的:者都是用spfa来做。
不同点,1:最长路是把dis数组初始化为0,负权spfa最短路还是inf
2:边权不一样最长路存的是add(u,v,d),而最短路存的是add(u,v,-d)
3: 最长路dis[s(起点)]=d,最短路是dis[s(起点)]=-d
4:松弛操作不一样,最长路是if(dis[j]<dis[t]+e[i].w),最短路是if(dis[j]>dis[t]+e[i].w)
(-------------------------------------------------------------------------------引用一下大佬的话,言简意赅,适合)
okk分析完毕上ACcode:(这种代码都贴了码哦)
第一种做法:(跑最长路)
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define inf 0x3f3f3f3f
const int N=250,M=3500;
struct E{
int to,w,next;
}e[M];
int head[N],cnt,dis[N],k[N];
bool vis[N];
int d,m,n,f,s,u,v,w,flag;
void add(int u,int v,int w){
e[++cnt]={v,w,head[u]},head[u]=cnt;
}
void spfa(){
for(int i=1;i<=n;i++) dis[i]=0;//初始化
dis[s]=d;
queue<int>q;
q.push(s);
k[s]++;
vis[s]=true;
while(!q.empty()){
int t=q.front();
if(++k[t]>n){
flag=1;
return;
}
q.pop();
vis[t]=false;
for(int i=head[t];i;i=e[i].next){
int j=e[i].to;
if(dis[j]<dis[t]+e[i].w){
dis[j]=dis[t]+e[i].w;
if(!vis[j]){
q.push(j);
vis[j]=true;
}
}
}
}
}
void solve(){
cin>>d>>m>>n>>f>>s;
for(int i=1;i<=m;i++){
cin>>u>>v;
add(u,v,d);
}
for(int i=1;i<=f;i++){
cin>>u>>v>>w;
add(u,v,(d-w));
}
spfa();
if(flag){
cout<<"-1"<<"\n";
return;
}
int mmax=-1;
for(int i=1;i<=n;i++){
mmax=max(mmax,dis[i]);
}
cout<<mmax<<"\n";
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int tt=1;
//cin>>tt;
while(tt--){
solve();
}
return 0;
}
第二种做法(spfa跑负权变最短路)
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define inf 0x3f3f3f3f
const int N=250,M=3500;
struct E{
int to,w,next;
}e[M];
int head[N],cnt,dis[N],k[N];
bool vis[N];
int d,m,n,f,s,u,v,w,flag;
void add(int u,int v,int w){
e[++cnt]={v,w,head[u]},head[u]=cnt;
}
void spfa(){
for(int i=1;i<=n;i++) dis[i]=inf;//初始化
dis[s]=-d;
queue<int>q;
q.push(s);
k[s]++;
vis[s]=true;
while(!q.empty()){
int t=q.front();
if(++k[t]>n){
flag=1;
return;
}
q.pop();
vis[t]=false;
for(int i=head[t];i;i=e[i].next){
int j=e[i].to;
if(dis[j]>dis[t]+e[i].w){
dis[j]=dis[t]+e[i].w;
if(!vis[j]){
q.push(j);
vis[j]=true;
}
}
}
}
}
void solve(){
cin>>d>>m>>n>>f>>s;
for(int i=1;i<=m;i++){
cin>>u>>v;
add(u,v,-d);
}
for(int i=1;i<=f;i++){
cin>>u>>v>>w;
add(u,v,-(d-w));
}
spfa();
if(flag){
cout<<"-1"<<"\n";
return;
}
int mmax=-1;
for(int i=1;i<=n;i++){
mmax=max(mmax,-dis[i]);
}
cout<<mmax<<"\n";
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int tt=1;
//cin>>tt;
while(tt--){
solve();
}
return 0;
}
over~