POJ -1062 昂贵的聘礼(前向星 && SPFA)

题目链接:昂贵的聘礼


   这个题对自己收获挺大的,模板要自己经常敲,才能理解,要自己经常敲,从能温故而知新,自己以前总结的建图方式,做题的时候要会用,要敢用,否则==NULL。


题意对于交换条件描述的有点不清楚,这里解释一下,假设8件物品,等级差距不能超过3,酋长LV 5,所以可以进行交换的LV区间是[2,5][3,6][4,7][5,8],不必考虑题目那一句,“但是如果他和某个地位较低的人进行了交易,地位较高的的人不会再和他交易,他们认为这样等于是间接接触,反过来也一样”。越看越晕,只要符合以上区间的都可以进行交换。


思路:开始看题时,自己的思路有点偏差,认为P神只能从价格最便宜、等级最低的那个人开始首次交易,后来敲了。。。再后来。。无从下手了,看了一下Discuss,噢,枚举啊,Discuss上的神牛门大多用Dijkstra 或 Bellman-Ford过的,还剪枝...俺还没学啊。然后,我想Bellman-Ford能过的SPFA肯定也能过,但是SPFA怎么敲,忘了。。又重新复习最短路 And 建图方式,开敲1遍A。中间的小细节自己处理的不好,还不会调程序,又叫P神过来了。。。。

ME        TIME

720kb    32ms


#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
const int Size = 99999;
const int INF = 1<<20;
const int N = 101;
const int MMM = 10010;
using namespace std;
int NN,M,l = 0;
struct node{
    int v,w,next;
}edge[MMM];
int p[N],lv[N],num,t;
int dis[N],vis[N],lim,low;
int q[MMM],head[MMM];

int SPFA(int S,int E)
{
    //printf("low = %d high = %d\n",low,lim);
    int s = 0,e = 0;
    for(int i = 1;i<=N;i++)
        dis[i] = p[1];
    dis[S] = 0;
    q[e++] = S;
    vis[S] = 1;
    while(s < e)
    {
        int tmp = q[s++];
        for(int i = head[tmp];i!=0;i=edge[i].next)
        {
       if((lv[edge[i].v]>=low && lv[edge[i].v]<=lim )&& (dis[edge[i].v]> dis[tmp] + edge[i].w))
            {
                dis[edge[i].v] = dis[tmp] + edge[i].w;
                if(!vis[edge[i].v])
                {
                    q[e++] = edge[i].v;
                    vis[edge[i].v] = 1;
                }
            }
        }
        vis[tmp] = 0;
    }
    return dis[E];
}
void add(int a,int b,int c) //前向星建图
{
    edge[t].v = b;
    edge[t].w = c;
    edge[t].next = head[a];
    head[a] = t;
    t++;
}
/*void Print()
{
    int k,i;
    for(i = 0; i <= NN; i++)
    {
        if(head[i])
        {
            for(k = head[i]; k != 0; k = edge[k].next)
          {
            printf("%d->%d %d\n", i, edge[k].v, edge[k].w);
          }
        }
    }
}*/
int main()
{
    int a,b;
    while(~scanf("%d%d",&M,&NN))
    {
        l = 0;
        t = 1;
        memset(head,0,sizeof(head));
        for(int i = 1;i<=NN;i++)
        {
            scanf("%d%d%d",&p[i],&lv[i],&num);
            add(0,i,p[i]);
            for(int j = 0;j<num;j++)
            {
             scanf("%d%d",&a,&b);
             add(a,i,b);
            }
        }
        /*puts("-------------");
        Print(); //打印图形
        puts("-------------");*/

        int minn = INF,flag = 0;
        for(int i = lv[1]-M;i<=lv[1];i++) //枚举所有可行交换
        {
            lim = i + M;
            low = i;
            memset(vis,0,sizeof(vis));
            flag = SPFA(0,1);
            (flag < minn)?(minn = flag):(minn=minn);
        }
        printf("%d\n",minn);
    }
    return 0;
}


  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值