XX Open Cup. Grand Prix of Korea G題 Lexicographically Minimum Walk(深搜)

題目

G題 Lexicographically Minimum Walk

題解

在這裏插入圖片描述

思路

要求s到t的字典序最小的路徑,有可能不可達或路徑無限長。

我們的貪心策略:要讓字典序最小,那每次我們都要選取所相連的字典序最小的那條邊,這樣字典序能夠做到最小,但是這樣有可能走進死衚衕裏去了,而實際上s和t是可達的。

那麼我們進行一個預處理,我們想要知道走哪些路是能到達t的,得出這些路之後,我們在這些路上進行上述的貪心策略即爲答案。

怎麼求s到t的可達路呢?
將原圖反建,以t爲起點跑一個dfs即可。這樣被標記上的點都是可達t的,我們只在這些點上進行貪心策略,即可求出答案。

代碼

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <string.h>
#include <cstdio>
#include <cstdlib>
#include <queue>
using namespace std;
#define MP(a, b) make_pair(a, b)
typedef pair <int, int> P;
const int maxn = 1e5 + 10;
int n, m, s, t;
vector <P> G[maxn];
vector <int> rev_G[maxn];
bool rev_vis[maxn];
bool G_vis[maxn];
vector <int> ans;

void dfs_rev(int u){
    rev_vis[u] = true;
    for(int i = 0; i < rev_G[u].size(); i++)
        if(!rev_vis[rev_G[u][i]])
            dfs_rev(rev_G[u][i]);
}

void dfs(int u){
    if(u == t){
        for(int i = 0; i < ans.size(); i++){
            printf("%d ", ans[i]);
        }
        exit(0);
    }
    if(G_vis[u]){
        printf("TOO LONG\n");
        exit(0);
    }
    G_vis[u] = true;
    for(int i = 0; i < G[u].size(); i++){
        if(rev_vis[G[u][i].first]){
            ans.push_back(G[u][i].second);
            dfs(G[u][i].first);
        }
    }
}

bool cmp(P a, P b){
    return a.second < b.second;
}

int main(){
    cin >> n >> m >> s >> t;
    int u, v, c;
    for(int i = 1; i <= m; i++){
        scanf("%d %d %d", &u, &v, &c);
        G[u].push_back(MP(v, c));
        rev_G[v].push_back(u);
    }
    for(int i = 1; i <= n; i++){
        sort(G[i].begin() , G[i].end(), cmp);
    }
    dfs_rev(t);//check rev_G
    if(!rev_vis[s]){
        return 0 * printf("IMPOSSIBLE\n");
    }
    dfs(s);//dfs G
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章