vijos1027-spfa&關鍵路徑-休息中的阿呆
阿新 • • 發佈:2018-12-24
https://vijos.org/p/1027
給定一個有向圖,n個頂點,m個邊。每個邊有時間作為邊權,問從1到n,最少花費多少時間可以把真個圖都過一遍(把每個頂點都過一遍)。並且輸出所有可能經過的點(用最少時間t走的所有可能經過的點)
思路:spfa改下方向就好了,把d陣列改成無窮小,關鍵路徑的輸出我是用一個vector存的。當進行鬆弛操作的時候,如果成功就改。
兩種輸出關鍵路徑的方法。
坑點:題目中說所有可能的點,意思是如果有兩條同樣長的點,那麼要一起輸出,最好的方法是erase和unique了。
我開始以為只要進行過鬆弛操作,只要把進行過鬆馳過操作的所有點(to和u都記錄,)通過去重就可以得到答案,但是其實不然,因為最長(短)路一定鬆馳,但是鬆馳不一定是最長(短)路
見下圖,紅色的區域發生過鬆弛操作,但是一定不可能在最短路中
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e3+4;
vector<pair<int,int> >g[maxn];
int d[maxn];
bool vis[maxn];
vector<int>kk[maxn];
int m;
int mp[maxn][maxn];
vector<int>w;
void dfs(int s,vector<int>q,int v){
if(!s){
for(int i=0;i<q.size();i++){
w.push_back(q[i]);
}
return;
}
for(int i=1;i<=m;i++){
vector<int>p(q.begin(),q.end());
if(d[i]==(s-mp[v][i])&&mp[v][i]){
p.push_back(i);
dfs(d[i],p,i);
}
}
return ;
}
void spfa(){
queue<int>q;
memset(vis,false,sizeof(vis));
memset(d,-0x3f3f3f3f,sizeof(d));
for(int i=0;i<maxn;i++)kk[i].clear();
q.push(1);
vis[1]=true;
d[1]=0;
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=false;
for(int i=0;i<g[u].size();i++){
int to=g[u][i].first;
int cost=g[u][i].second;
if(d[to]<d[u]+cost){
d[to]=d[u]+cost;
if(!vis[to]){
q.push(to);
vis[to]=true;
}
}
else if(d[to]==d[u]+cost){
for(int x=0;x<kk[u].size();x++){
kk[to].push_back(kk[u][x]);
}
kk[to].push_back(u);
}
}
}
int s=d[m+1];
printf("%d\n",s);
vector<int>ss;ss.clear();
w.clear();
dfs(s,ss,m+1);
w.push_back(m+1);
sort(w.begin(),w.end());
w.erase(unique(w.begin(),w.end()),w.end());
for(int i=0;i<w.size();i++){
if(!i)
printf("%d",w[i]);
else
printf(" %d",w[i]);
}
printf("\n");
}
int main()
{ int n,a,b,c;
scanf("%d%d",&m,&n);
for(int i=0;i<n;i++){
scanf("%d%d%d",&a,&b,&c);
g[a].push_back(make_pair(b,c));
mp[a][b]=c;
mp[b][a]=c;
}
spfa();
return 0;
}
第一個程式碼還是有點麻煩,得用鄰接矩陣(如果存圖也用鄰接矩陣就沒那麼麻煩了)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e3+4;
vector<pair<int,int> >g[maxn];
int d[maxn];
bool vis[maxn];
vector<int>kk[maxn];
int m;
void spfa(){
queue<int>q;
memset(vis,false,sizeof(vis));
memset(d,-0x3f3f3f3f,sizeof(d));
for(int i=0;i<maxn;i++)kk[i].clear();
q.push(1);
vis[1]=true;
d[1]=0;
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=false;
for(int i=0;i<g[u].size();i++){
int to=g[u][i].first;
int cost=g[u][i].second;
if(d[to]<d[u]+cost){
d[to]=d[u]+cost;
kk[to].clear();
for(int x=0;x<kk[u].size();x++){
kk[to].push_back(kk[u][x]);
}
kk[to].push_back(u);
if(!vis[to]){
q.push(to);
vis[to]=true;
}
}
else if(d[to]==d[u]+cost){
for(int x=0;x<kk[u].size();x++){
kk[to].push_back(kk[u][x]);
}
kk[to].push_back(u);
}
}
}
//for(int i=1;i<=m+1;i++)
//printf("**%d\n",d[i]);
sort(kk[m+1].begin(),kk[m+1].end());
kk[m+1].erase(unique(kk[m+1].begin(),kk[m+1].end()),kk[m+1].end());
printf("%d\n",d[m+1]);
for(int i=0;i<kk[m+1].size();i++){
if(!i)
printf("%d",kk[m+1][0]);
else
printf(" %d",kk[m+1][i]);
}
printf(" %d",m+1);
printf("\n");
}
int main()
{ int n,a,b,c;
scanf("%d%d",&m,&n);
for(int i=0;i<n;i++){
scanf("%d%d%d",&a,&b,&c);
g[a].push_back(make_pair(b,c));
}
//puts("!!!");
spfa();
return 0;
}