【vijos】【floyd求最小環】觀光旅遊

背景

湖南師大附中成爲百年名校之後,每年要接待大批的遊客前來參觀。學校認爲大力發展旅遊業,可以帶來一筆可觀的收入。

描述

學校裏面有N個景點。兩個景點之間可能直接有道路相連,用Dist[I,J]表示它的長度;否則它們之間沒有直接的道路相連。這裏所說的道路是沒有規定方向的,也就是說,如果從I到J有直接的道路,那麼從J到I也有,並且長度與之相等。學校規定:每個遊客的旅遊線路只能是一個迴路(好霸道的規定)。也就是說,遊客可以任取一個景點出發,依次經過若干個景點,最終回到起點。一天,Xiaomengxian決定到湖南師大附中旅遊。由於他實在已經很累了,於是他決定儘量少走一些路。於是他想請你——一個優秀的程序員——幫他求出最優的路線。怎麼樣,不是很難吧?(摘自《鬱悶的出納員》)

格式

輸入格式

對於每組數據:
第一行有兩個正整數N,M,分別表示學校的景點個數和有多少對景點之間直接有邊相連。(N<=100,M<=10000)
以下M行,每行三個正整數,分別表示一條道路的兩端的編號,以及這條道路的長度。

輸出格式

對於每組數據,輸出一行:
如果該回路存在,則輸出一個正整數,表示該回路的總長度;否則輸出“No solution.”(不要輸出引號)

分析

就是找無向圖的最小環問題。如果用Dijsktra,每次刪掉圖中的一條邊(u,v),找從u到v的最短路,再加上w[u,v]即可,時間複雜度爲O(E(E+VlogV)),然而題目數據給的E可能很大…
所以用Floyd的修改版寫好了…

代碼

#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 100+10
#define INF 1000000//這道題好坑的,INF太大了會WA?
using namespace std;

int n,m,a,b,c,dist[maxn][maxn],edge[maxn][maxn],ans=INF;

int main(){
while(scanf("%d%d",&n,&m)!=EOF){
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++) if(i==j) {
            edge[i][j]=dist[i][j]=0;
        } else {
            edge[i][j]=dist[i][j]=INF;
        }
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&a,&b,&c);
        dist[a][b]=dist[b][a]=c;
        edge[a][b]=edge[b][a]=c;
    }
    //設環的起點(終點)爲i,那麼環可以表示爲i->k->j->x1,x2...(不經過k)->i
    //環的長度可以表示爲i->j經過k的dist+i->不經過k的dist
    //i->j經過k的dist普通floyd就能求到,不經過k的dist需要構造
    //在求這個環時,保持k是最大值,那麼所有x1,x2...都比k要小
    //循環遍歷至k-1時存儲的就是j->x1,x2...->i的最小值 
    for(int k=1;k<=n;k++){//k是用來更新的中間點,保持k比i,j都要大, 
        for(int i=1;i<k;i++)//floyd每次更新從i開始到j結束,中間經過k的距離
            for(int j=i+1;j<k;j++){
                ans=min(ans,dist[i][j]+edge[i][k]+edge[k][j]);
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
    } 
    if(ans<INF) printf("%d\n",ans);
    else printf("No solution.\n");
    ans=INF;
}
    return 0;
}
發佈了62 篇原創文章 · 獲贊 12 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章