POJ 1062 昂贵的聘礼

这题说实在话就是模版题,可是你要是不知道模版是怎么工作的,有模版也没用,这个题就是个例子。

所以说这个题给了我个教训就是:有了模版也得自己敲,要不然关键时刻是不管用的。

这个题的关键在于:

1、虚拟一个节点0,所有物品的价值被表示为这个点到对应物品编号点的边的权值。

2、相关联的物品连一条权为优惠价格的边。

3、求节点0与节点1之间的最短路就行了。

要注意的的是:

1、酋长不一定是最高级,所以控制交易等级范围时不一定酋长是等级上界,需要对等级范围进行枚举。

2、交易等级范围就是等级差的大小,因为间接交易超过等级差也不行。

下面是代码:

#include <stdio.h>
const int V=105;
const int E=10005;
struct node
{
    int mon,lv;
} wu[V];
struct node1
{
    int u,v,w;
} edge[E];
int m,l,r,dis[V],vis[V];
void bellmam_ford(int n)
{
    int i,j,flat;
    for(i=0; i<n; i++)//初始化0点到各点的权值,及各物品的价值,dis[0]=0。
    {
        dis[i]=wu[i].mon;
    }
    flat=0;
    for(i=1; i<=n; i++)
    {
        for(j=0; j<m; j++)
        {
            if(wu[edge[j].u].lv>=l&&wu[edge[j].u].lv<=r&&wu[edge[j].v].lv>=l&&wu[edge[j].v].lv<=r&&dis[edge[j].u]>dis[edge[j].v]+edge[j].w)
            {
                dis[edge[j].u]=dis[edge[j].v]+edge[j].w;
                flat=1;
            }
        }
        if(!flat)
        {
            break;
        }
    }
}
int main()
{
    int M,N;
    while(scanf("%d%d",&M,&N)!=EOF)
    {
        int i,j,t;
        m=0;
        for(i=1; i<=N; i++)//进行输入,建立有向边的邻接表。
        {
            scanf("%d%d%d",&wu[i].mon,&wu[i].lv,&t);
            edge[m].u=0;
            edge[m].v=i;
            edge[m].w=wu[i].mon;
            m++;
            for(j=0; j<t; j++)
            {
                scanf("%d%d",&edge[m].v,&edge[m].w);
                edge[m].u=i;
                m++;
            }
        }
        int min1=wu[1].mon;
        wu[0].lv=wu[1].lv;
        for(l=wu[1].lv-M; l<=wu[1].lv; l++)//枚举等级范围,范围长度为M。
        {
            r=l+M;
            bellmam_ford(N+1);//因为多虚拟一个点,所以是n+1个点
            if(min1>dis[1])
            {
                min1=dis[1];
            }
        }
        printf("%d\n",min1);
    }
    return 0;
}


posted @ 2013-08-06 16:55  、小呆  阅读(108)  评论(0编辑  收藏  举报