天天看點

POJ 1062 迪傑斯特拉

昂貴的聘禮

Time Limit: 1000MS Memory Limit: 10000K

Total Submissions: 42271 Accepted: 12369

Description

年輕的探險家來到了一個印第安部落裡。在那裡他和酋長的女兒相愛了,于是便向酋長去求親。酋長要他用10000個金币作為聘禮才答應把女兒嫁給他。探險家拿不出這麼多金币,便請求酋長降低要求。酋長說:”嗯,如果你能夠替我弄到大祭司的皮襖,我可以隻要8000金币。如果你能夠弄來他的水晶球,那麼隻要5000金币就行了。”探險家就跑到大祭司那裡,向他要求皮襖或水晶球,大祭司要他用金币來換,或者替他弄來其他的東西,他可以降低價格。探險家于是又跑到其他地方,其他人也提出了類似的要求,或者直接用金币換,或者找到其他東西就可以降低價格。不過探險家沒必要用多樣東西去換一樣東西,因為不會得到更低的價格。探險家現在很需要你的幫忙,讓他用最少的金币娶到自己的心上人。另外他要告訴你的是,在這個部落裡,等級觀念十分森嚴。地位差距超過一定限制的兩個人之間不會進行任何形式的直接接觸,包括交易。他是一個外來人,是以可以不受這些限制。但是如果他和某個地位較低的人進行了交易,地位較高的的人不會再和他交易,他們認為這樣等于是間接接觸,反過來也一樣。是以你需要在考慮所有的情況以後給他提供一個最好的方案。

為了友善起見,我們把所有的物品從1開始進行編号,酋長的允諾也看作一個物品,并且編号總是1。每個物品都有對應的價格P,主人的地位等級L,以及一系列的替代品Ti和該替代品所對應的”優惠”Vi。如果兩人地位等級差距超過了M,就不能”間接交易”。你必須根據這些資料來計算出探險家最少需要多少金币才能娶到酋長的女兒。

Input

輸入第一行是兩個整數M,N(1 <= N <= 100),依次表示地位等級差距限制和物品的總數。接下來按照編号從小到大依次給出了N個物品的描述。每個物品的描述開頭是三個非負整數P、L、X(X < N),依次表示該物品的價格、主人的地位等級和替代品總數。接下來X行每行包括兩個整數T和V,分别表示替代品的編号和”優惠價格”。

Output

輸出最少需要的金币數。

Sample Input

1 4

10000 3 2

2 8000

3 5000

1000 2 1

4 200

3000 2 1

4 200

50 2 0

Sample Output

5250

題意:

如上。 。

題解:

尋找滿足等級條件裡的最短路。當時考慮枚舉每個點,以這個點和起始點的等級為基準。但是這樣并不能保證所有的情況。是以應該枚舉一個範圍[LL,RR]RR最小到酋長的等級,最大到酋長的等級+M。然後求出每個範圍裡的最小花費。枚舉完所有範圍,就能找出最小的花費。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#define f(i,a,b) for(i = a;i<=b;i++)
#define fi(i,a,b) for(i = a;i>=b;i--)

using namespace std;

struct Po
{
    int from,to,v;
};

struct PP
{
    int x,y;
    friend bool operator<(PP a,PP b)
    {
        return a.y>b.y;
    }
};

vector<Po> G[];
int d[];
int Lever[];
int p[];
int LL,RR;
int M,N;

bool IsTrue(int kk){
    if(kk>=LL&&kk<=RR)
        return true;
    else
        return false;
}

int Dij()
{
    memset(d,,sizeof(d));
    memset(p,,sizeof(p));
    d[] = ;
    priority_queue<PP>pq;
    int j;
    PP tem1;
    tem1.x = ;
    tem1.y = ;
    pq.push(tem1);
    while(!pq.empty())
    {
        tem1 = pq.top();pq.pop();
        PP tem2 = tem1;
        if(!IsTrue(Lever[tem1.x])) continue;
        if(p[tem1.x]) continue;
        else p[tem1.x] = ;
        if(G[tem2.x].empty()) continue;
        f(j,,G[tem2.x].size()-)
        {
            Po vv = G[tem2.x][j];
            if(!IsTrue(Lever[vv.to])) continue;
            if(d[vv.to]>d[vv.from]+vv.v)
            {
                d[vv.to]=d[vv.from]+vv.v;
                tem1.x = vv.to;
                tem1.y = d[vv.to];
                pq.push(tem1);
            }
        }
    }
    int i,Min = ;
    f(i,,+N)
        if(IsTrue(Lever[i])&&d[i]!=&&d[i]<Min)
            Min = d[i];
    return Min;
}

int main()
{
//    freopen("data.in","r",stdin);

    while(~scanf("%d%d",&M,&N))
    {
        int i,j;
        int P,L,X;
        f(i,,N) G[i].clear();
        scanf("%d%d%d",&P,&L,&X);
        int MinLim = L;
        Po tem;
        Lever[] = Lever[] = L;
        tem.from = ;tem.to = +;tem.v = P;
        G[].push_back(tem);
        f(i,,X)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            tem.to = a;tem.v = b;
            G[].push_back(tem);
        }

        f(i,,N)
        {
            scanf("%d%d%d",&P,&L,&X);
            Lever[i] = Lever[i+] = L;
            tem.from = i;
            tem.to = +i;
            tem.v = P;
            G[i].push_back(tem);
            f(j,,X)
            {
                int a,b;
                scanf("%d%d",&a,&b);
                tem.to = a;
                tem.v = b;
                G[i].push_back(tem);
            }
        }
        int Min = ;
        for(RR = MinLim,LL = MinLim - M;LL<=MinLim;LL++,RR++){
            int kk = Dij();
            if(kk<Min)
                Min = kk;
        }
        printf("%d\n",Min);
    }
    return ;
}