1. 程式人生 > >vijos1027-spfa&關鍵路徑-休息中的阿呆

vijos1027-spfa&關鍵路徑-休息中的阿呆

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;
}