1. 程式人生 > >BZOJ_1916_[Usaco2010 Open]沖浪_分層圖+拓撲排序+DP

BZOJ_1916_[Usaco2010 Open]沖浪_分層圖+拓撲排序+DP

src 找到 -- 無法 不可 EDA image 否則 她是

BZOJ_1916_[Usaco2010 Open]沖浪_分層圖+拓撲排序+DP

Description

受到秘魯的馬丘比丘的新式水上樂園的啟發,Farmer John決定也為奶牛們建 一個水上樂園。當然,它最大的亮點就是新奇巨大的水上沖浪。超級軌道包含 E (1 <= E <=150,000)條小軌道連接著V (V <= 50,000)個水池,編號為1..V。每個小軌道必須按照特定的方向運行,不能夠反向運行。奶牛們從1號水池出發,經過若幹條小軌道,最終到達V號水池。每個水池(除了V號和1號之外,都有至少一條小軌道進來和一條小軌道出去,並且,一頭奶牛從任何一個水池到達V 號水池。最後,由於這是一個沖浪,從任何一個水池出發都不可能回到這個水池) 每條小軌道從水池P_i到水池Q_i (1 <= P_i <= V; 1<= Q_i <= V; P_i != Q_i), 軌道有一個開心值F_i (0 <= F_i <= 2,000,000,000),Bessie總的開心值就是經過的所有軌道的開心值之和。Bessie自然希望越開心越好,並且,她有足夠長的時間在軌道上玩。因此,她精心地挑選路線。但是,由於她是頭奶牛,所以,會有至多K (1 <= K <= 10)次的情況,她無法控制,並且隨機從某個水池選擇了一條軌道(這種情況甚至會在1號水池發生) 如果Bessie選擇了在最壞情況下,最大化她的開心值,那麽,她在這種情況下一次沖浪可以得到的最大開心值是多少? 在樣例中,考慮一個超級軌道,包含了3個水池(在圖中用括號表示)和4條小軌道,K的值為1 (開心值在括號外表示出來,用箭頭標識) 技術分享圖片
她總是從1號水池出發,抵達3號水池。如果她總是可以自己選擇,就是不會發生不能控制的情況她可以選擇從1到2(這條軌道開心值為5),再從2到3(開心值為5),總的開心值為5+5=10。但是,如過她在1號水池失去控制,直接到了3,那麽開心值為9,如果她在2號水池失去控制,她總的開心值為8。Bessie想要找到最大化開心值的方案,可以直接從1到3,這樣,如果在1號水池失去控制,這樣,她就不會在2號水池失去控制了,就能夠得到10的開心值。因此,她的開心值至少為9

Input

* 第一行: 三個用空格隔開的整數: V, E, 和 K * 第2到第E+1行: 第i+1行包含三個用空格隔開的整數: P_i, Q_i, and F_i

Output

* 第一樣: 一行一個整數表示在最壞情況下最大化的開心值

Sample Input

3 4 1
2 3 5
1 2 5
1 3 9
2 3 3

Sample Output

9


由於K很小,可以像分層圖那樣設狀態,F[i][j]表示從i到n,使用j次改變的最短路。

分兩步轉移,是否使用改變,如果使用則找一個最小的轉移,否則找一個最長的。

然後這個建反圖拓撲排序即可。

代碼:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 50050
#define M 150050
typedef long long ll;
ll f[N][11],mn[N][11],mx[N][11];
int head[N],to[M],nxt[M],cnt,val[M],Q[N],l,r,in[N],n,m,K;
inline void add(int u,int v,int w) {
    to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w;
}
int main() {
    scanf("%d%d%d",&n,&m,&K);
    int i,x,y,z,j;
    for(i=1;i<=m;i++) {
        scanf("%d%d%d",&x,&y,&z); add(y,x,z); in[x]++;
    }
    for(i=0;i<=K;i++) f[n][i]=0;
    memset(mn,0x3f,sizeof(mn));
    Q[r++]=n;
    while(l<r) {
        x=Q[l++];
        for(i=0;i<=K;i++) f[x][i]=min(mx[x][i],mn[x][i]);
        for(i=head[x];i;i=nxt[i]) {
            for(j=0;j<=K;j++) mx[to[i]][j]=max(mx[to[i]][j],f[x][j]+val[i]);
            for(j=0;j<K;j++) mn[to[i]][j]=min(mn[to[i]][j],f[x][j+1]+val[i]);
            if((--in[to[i]])==0) Q[r++]=to[i];
        }
    }
    printf("%lld\n",f[1][0]);
}

BZOJ_1916_[Usaco2010 Open]沖浪_分層圖+拓撲排序+DP