P2901 [USACO08MAR]牛慢跑Cow Jogging

題目描述  傳送門

Bessie has taken heed of the evils of sloth and has decided to get fit by jogging from the barn to the pond several times a week. She doesn't want to work too hard, of course, so she only plans to jog downhill to the pond and then amble back to the barn at her leisure.

Bessie also doesn't want to jog any too far either, so she generally takes the shortest sequence of cow paths to get to the pond. Each of the M (1 <= M <= 10,000) cow paths connects two pastures

conveniently numbered 1..N (1 <= N <= 1000). Even more conveniently, the pastures are numbered such that if X>Y then the cow path from pasture X to pasture Y runs downhill. Pasture N is the barn (at the top of the hill) and pasture 1 is the pond (at the bottom).

Just a week into her regimen, Bessie has begun to tire of always taking the same route to get to the pond. She would like to vary her route by taking different cow paths on different days. Specifically, Bessie would like to take exactly K (1 <= K <= 100) different routes for variety. To avoid too much exertion, she wants these to be the K shortest routes from the barn to the pond. Two routes are considered different if they comprise different sequences of cow paths.

Help Bessie determine how strenuous her workout will be by determining the lengths of each of the K shortest routes on the network of pastures. You will be supplied a list of downhill cow paths from X_i to Y_i along with the cow path's length: (X_i, Y_i, D_i) where (1 <= Y_i < X_i; Y_i < X_i <= N). Cowpath i has length D_i (1 <= D_i <= 1,000,000).

貝西嚐到了懶惰的惡果——爲了減肥,她不得不決定每週花幾次時間在牛棚和池塘之間慢跑。但貝西並不想太累,所以她打算只跑從牛棚到池塘的下坡路,然後再慢慢地從池塘走回牛棚。

同時,貝西也不想跑得太遠,所以她只想沿着通向池塘的最短路徑跑步。在牧場裏,每條道路連接了兩個結點(這些結點的編號爲1到N,1≤N≤1000)。另外,如果X>?,說明結點X的地勢要高於Y,所以下坡的道路是從X通向Y的,貝西所在牛棚的編號爲N(最高點),池塘的編號爲1(最低點)。

而然,一週之後,貝西對單調的路線厭倦了,她希望每天可以跑不同的路線,比如說,最好能有K (1≤K≤100)種不同的選擇。爲了不至於跑得太累,她希望這K條路徑是從牛棚到池塘的最短的K條路徑。

請幫助貝西算算她的運動量,即找出網絡裏最短的K條路徑的長度。假設每條道路用(Xi,Yi,Di)表示,其中1≤Yi<Xi≤N,表示這條道路從Xi出發到Yi,其長度爲Di (1≤Di≤1,000,000)。

輸入格式

* Line 1: Three space-separated integers: N, M, and K

* Lines 2..M+1: Line i+1 describes a downhill cow path using three space-separated integers: X_i, Y_i, and D_i

輸出格式

* Lines 1..K: Line i contains the length of the i-th shortest route or -1 if no such route exists. If a shortest route length occurs multiple times, be sure to list it multiple times in the output.

輸入輸出樣例

輸入 #1

5 8 7 

5 4 1 

5 3 1 

5 2 1 

5 1 1 

4 3 4 

3 1 1 

3 2 1 

2 1 1 

輸出 #1

1 

2 

2 

3 

6 

7 

-1 

說明/提示

The routes are (5-1), (5-3-1), (5-2-1), (5-3-2-1), (5-4-3-1),

(5-4-3-2-1).

 

思路:K短路徑模板題,先建立反向圖,找到各個頂點到目的點的最短距離(可以用Dijkstra或者是spfa,看個人喜好了)。然後再用A*算法(廣度優先搜索+加剪枝),一點點得出最短的前K條路經。 其中用於剪枝的評估函數是f(u) = dis0[u] + dis[u],其中 dis0[u] 表示:N~u的最短路徑,dis[u] 表示 u~1的最短路徑。根據評估函數的從小到大依次求出圖的前K短路徑.

 

AC代碼:

#include <bits/stdc++.h>

using namespace std;
#define io ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define mset(a, n) memset(a, n, sizeof(a))
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef pair<int,int> PII;
typedef pair<int,PII> PPI;
typedef pair<ll, ll> PLL;
const int maxn =  1e3+5;

int V, E, K; int tot;
int dis[maxn];
bool vis[maxn];

struct node{
    int to;
    int val;
    node(){}
    node(int _to, int _val): to(_to), val(_val){}
    bool operator < (const node &a) const {
        return val+dis[to] > a.val+dis[a.to];
    }
};
struct Edges{
    int to;
    int val;
    Edges(){}
    Edges(int _to, int _val): to(_to), val(_val){}
};
vector<Edges> G[maxn], lG[maxn];
int ans[maxn];

void addedge(int u, int v, int val){
    G[u].pb(Edges(v, val));
    lG[v].pb(Edges(u, val));
}

void spfa(){
    mset(vis,false);
    mset(dis,0x3f3f);

    queue<int> Q;
    Q.push(1);
    vis[1] = true;
    dis[1] = 0;

    while(!Q.empty()){
        int u = Q.front(); Q.pop();
        vis[u] = false;
        for(int i=0;i<lG[u].size();i++){
            int v = lG[u][i].to, val = lG[u][i].val;
            if(dis[v] > dis[u]+val){
                dis[v] = dis[u]+val;
                if(!vis[v]){
                    Q.push(v);
                    vis[v] = true;
                }
            }
        }
    }

}

void a_star(){
    priority_queue<node> Q;
    Q.push(node(V,0));

    while(!Q.empty()){
        node nw = Q.top(); Q.pop();
        if(nw.to == 1){
            tot++;
            ans[tot] = nw.val;
            if (tot>K) return;
        }
        for(int i = 0; i<G[nw.to].size();i++){
            Q.push(node(G[nw.to][i].to, nw.val+G[nw.to][i].val));
        }
    }
    return;
}

int main(){
    scanf("%d%d%d", &V, &E, &K);
    for(int i=1;i<=E;i++){
        int u,v,val;
        scanf("%d%d%d", &u, &v, &val);
        addedge(u,v,val);
    }
    mset(ans,-1);
    spfa();
    tot = 0;
    a_star();
    for(int i=1;i<=K;i++){
        printf("%d\n", ans[i]);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章