题目描述 Description
年轻的探险家来到了一个印第安部落里。在那里他和酋长的女儿相爱了,于是便向酋长去求亲。酋长要他用10000个金币作为聘礼才答应把女儿嫁给他。探险家拿不出这么多金币,便请求酋长降低要求。酋长说:“嗯,如果你能够替我弄到大祭司的皮袄,我可以只要8000金币。如果你能够弄来他的水晶球,那么只要5000金币就行了。”探险家就跑到大祭司那里,向他要求皮袄或水晶球,大祭司要他用金币来换,或者替他弄来其他的东西,他可以降低价格。探险家于是又跑到其他地方,其他人也提出了类似的要求,或者直接用金币换,或者找到其他东西就可以降低价格。不过探险家没必要用多样东西去换一样东西,因为不会得到更低的价格。探险家现在很需要你的帮忙,让他用最少的金币娶到自己的心上人。另外他要告诉你的是,在这个部落里,等级观念十分森严。地位差距超过一定限制的两个人之间不会进行任何形式的直接接触,包括交易。他是一个外来人,所以可以不受这些限制。但是如果他和某个地位较低的人进行了交易,地位较高的的人不会再和他交易,他们认为这样等于是间接接触,反过来也一样。因此你需要在考虑所有的情况以后给他提供一个最好的方案。

为了方便起见,我们把所有的物品从1开始进行编号,酋长的允诺也看作一个物品,并且编号总是1。每个物品都有对应的价格P,主人的地位等级L,以及一系列的替代品Ti和该替代品所对应的“优惠”Vi。如果两人地位等级差距超过了M,就不能“间接交易”。你必须根据这些数据来计算出探险家最少需要多少金币才能娶到酋长的女儿。

输入描述 Input Description
输入包括了多个测试数据。每个测试数据的第一行是两个整数M,N(1<=N<=100),依次表示地位等级差距限制和物品的总数。接下来按照编号从小到大依次给出了N个物品的描述。每个物品的描述开头是三个非负整数P、L、X(X<N),依次表示该物品的价格、主人的地位等级和替代品总数。接下来X行每行包括两个整数T和V,分别表示替代品的编号和“优惠价格”。

输出描述 Output Description
对于每个测试数据,在单独一行内输出最少需要的金币数。

样例输入 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

有向图 有向图 有向图 (重要的事情说三遍)
讨论了好久才明白为什么不能建无向图,因为可能本来是通过i来买j,无向可能产生通过j来买i的情况。
把与酋长地位相差M以上的点扔掉,直接建图的时候忽略就OK hhh
设置一个点0,将直接买物品i的价格定义为0-i的权值,然后若能通过i买到j ,建立j到i的有向边,然后求0 - 1的最短路径就OK,

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<string>
#include<cstring>
#define pa pair<int,int>
using namespace std;

struct node
{
    int x,y,z,next;
}t[1000010];

int n,m,p,x,y,z,ans,tot = 0;
bool v[100010];
int head[100010],d[100010],a[105][105],k[105];

void build(int x,int y,int z)
{
    //printf("%d %d %d\n",x,y,z);
    t[++tot].x = x;
    t[tot].y = y;
    t[tot].z = z;
    t[tot].next = head[x];
    head[x] = tot;
}

/*void spfa(int s)
{
    queue<int>q;
    for(int i = 1;i <= n; ++i)
    {
        d[i] = 1e9;
        v[i] = 0;
    }
    v[s] = 1; d[s] = 0;
    q.push(s);
    while(!q.empty())
    {
        int tmp = q.front();
        q.pop();
        for(int i = head[i];i != -1;i = t[i].next)
        {
            if(d[t[i].y] > d[tmp] + t[i].z)
            {
                d[t[i].y] = d[tmp] + t[i].z;
            }
            if(!v[t[i].y])
            {
                q.push(t[i].y);
                v[t[i].y] = 1;
               // if(++in[y] > n) 判断负环
            }
        }
    }
}*/
void dij(int start)
{
    priority_queue<pa,vector<pa>,greater<pa> >q;
    for(int i = 1;i <= n; ++i) d[i] = 2147483647;
    d[start] = 0;
    q.push(make_pair(0,start));
    while(!q.empty())
    {
        int now = q.top().second;
        q.pop();
        for(int i = head[now];i;i = t[i].next)
        {
            if(d[now] + t[i].z < d[t[i].y])
            {
                d[t[i].y] = d[now] + t[i].z;
                q.push(make_pair(d[t[i].y],t[i].y));
            }
        }
    }
}

int main()
{
    scanf("%d%d",&m,&n);
    //memset(head,-1,sizeof(head));
    for(int i = 1;i <= n; ++i)
    {
        scanf("%d%d%d",&p,&k[i],&x);
        a[0][i] = p;
        for(int j = 1;j <= x; ++j)
        {
            scanf("%d%d",&y,&z);
            a[y][i] = z;
        }
    }
    k[0] = k[1];
    for(int i = 0;i <= n; ++i)
    {
        for(int j = 0; j <= n; ++j)
            if(m >= abs(k[i] - k[1]) && m >= abs(k[j] - k[1]) && a[i][j])
            {
                build(i,j,a[i][j]);
            }
    }
   /* scanf("%d%d%d",&p,&K,&x);
    a[0][1] = p;
    for(int i = 1;i <= x; ++i)
    {
        scanf("%d%d",&y,&z);
        a[1][y] = z;
    }
    for(int i = 2;i <= n; ++i)
    {
        scanf("%d%d%d",&p,&k,&x);
        if(m >= abs(K - k)) build(0,i,p);
        for(int j = 1;j <= x; ++j)
        {
            scanf("%d%d",&y,&z);
            if(m >= abs(K - k))
            {
               // cout<<k<<endl;
                build(i,y,z);
                build(y,i,z);
            }
        }
    }*/
    //spfa(0);
    dij(0);
    ans = 2147483647;
    //for(int i = 0;i <= n; ++i)ans = min(ans,d[i]);
    printf("%d\n",d[1]);
    return 0;
}

本来想写SPFA的,结果写废了hhh
迪杰斯特拉比较稳定,所以用它写
代码写的真丑