POJ--1062--昂贵的聘礼【dijkstra_heap+枚举】最短路

链接:http://poj.org/problem?id=1062

题意不说了,中文的

“但是如果他和某个地位较低的人进行了交易,地位较高的的人不会再和他交易,他们认为这样等于是间接接触,反过来也一样。” 这句话一开始没懂,看discuss里说的之后才明白,实际上你能交易的等级范围为 l[i]~l[i]+m,或者l[i]-m~l[i],其中l[i]是第i个人的等级,m是等级差距限制。

这道题建图,如果对于第 i 个人来说,j 可以通过物品 + t 来交易第 i 个人的物品,则在他们之间建一条有向路径,方向 j → i ,权值 t ,然后新增一个节点0,从0到任何一点都有一条单向路径,权值为那一点本身的价值。我们要做的就是从0点出发,找到到达1点的最小值,即dist[1]。

但是等级限制是个问题,刚开始没想到,看了别人的解题报告,大部分人是枚举,以第i个人的等级为上限(也可以为下限),如果剩下的人里有等级比他高的,就标记为已访问,如果有等级比他低的超过了m的,也标记为已访问,找最短路时就不做处理。然后枚举以这n个人的等级为最大值的最短路情况,找到最小的dist[1]。

需要注意的是:

1. 每次标记时会标记vis数组1~n的值,但是不会标记0,0需要自己手动标记,因为这个WA了一发。

2. 还有就是dijkstra_heap的优先队列里,找到邻接表比较路径长度时没有判断出边的点是否已访问,因为前几次都没加所以也没有注意,WA了一发,直到发现discuss里有组数据过不了:

1 5

10000 3 3

2 8000

3 5000

5 1000

1000 2 1

4 200

3000 2 1

4 200

50 2 0

50 6 0

正解是5250。方式为4→3→1。

而我的输出是1050,因为枚举第五个人的时候,其他四个由于不符合等级限制都被标记了已访问,但是0没被访问,0还是走一遍,发现5未被标记,5也入队,由于判断里没有判断出边的点是否已访问,5→1直接更新了dist[1],然后1入队,发现1已访问,才退出,但是此时dist[1]的值已是1050,所以得到了错误的答案。解决方法就是多加一个是否已访问的判断。

#include<cstring>
#include<string>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 100100
#define eps 1e-7
#define INF 0x7FFFFFFF
#define seed 131
#define ll long long
#define ull unsigned ll
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

struct node{
    int u,v,next;
}edge[10100];
struct NODE{
    int u,dis;
    bool operator < (const NODE &t) const{
        return t.dis<dis;
    }
};
int vis[110],dist[110],head[110];
int n,m,cnt,p[110],l[110];
void add_edge(int a,int b,int c){
    edge[cnt].u = b;
    edge[cnt].v = c;
    edge[cnt].next = head[a];
    head[a] = cnt++;
}
void dijkstra_heap(){
    int i,j;
    NODE t1,t2;
    for(i=0;i<=n;i++)   dist[i] = INF;
    dist[0] = 0;
    vis[0] = 0;
    t1.u = 0;
    t1.dis = 0;
    priority_queue<NODE>q;
    q.push(t1);
    while(!q.empty()){
        t1 = q.top();
        q.pop();
        if(vis[t1.u])   continue;
        vis[t1.u] = 1;
        for(i=head[t1.u];i!=-1;i=edge[i].next){
            int x = edge[i].v;
            if(!vis[edge[i].u]&&dist[t1.u]+x<dist[edge[i].u]){  //没判断!vis[edge[i].u] WA出翔
                dist[edge[i].u] = dist[t1.u] + x;
                t2.u = edge[i].u;
                t2.dis = dist[edge[i].u];
                q.push(t2);
            }
        }
    }
}
int main(){
    int i,j,x,a,b;
    while(scanf("%d%d",&m,&n)!=EOF){
        memset(head,-1,sizeof(head));
        memset(vis,0,sizeof(vis));
        cnt = 0;
        for(i=1;i<=n;i++){
            scanf("%d%d%d",&p[i],&l[i],&x);
            while(x--){
                scanf("%d%d",&a,&b);
                add_edge(a,i,b);
            }
        }
        for(i=1;i<=n;i++){
            add_edge(0,i,p[i]);
        }
        int minm = INF;
        for(i=1;i<=n;i++){
            int mm = l[i];
            for(j=1;j<=n;j++){
                if(l[j]>mm||mm-l[j]>m)  vis[j] = 1;
                else    vis[j] = 0;
                //cout<<i<<" "<<vis[j]<<endl;
            }
            dijkstra_heap();
            if(dist[1]<minm)    minm = dist[1];
        }
        printf("%d\n",minm);
    }
    return 0;
}

POJ--1062--昂贵的聘礼【dijkstra_heap+枚举】最短路

时间: 2024-11-14 07:06:27

POJ--1062--昂贵的聘礼【dijkstra_heap+枚举】最短路的相关文章

poj 1062 昂贵的聘礼 (dijkstra最短路)

题目链接:http://poj.org/problem?id=1062 昂贵的聘礼 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 36799   Accepted: 10616 Description 年轻的探险家来到了一个印第安部落里.在那里他和酋长的女儿相爱了,于是便向酋长去求亲.酋长要他用10000个金币作为聘礼才答应把女儿嫁给他.探险家拿不出这么多金币,便请求酋长降低要求.酋长说:"嗯,如果你能够替我弄到大祭司的

POJ 1062 昂贵的聘礼详解最短路变形

POJ上难得一见的中文题…… 思路:建立一个以0为源点的地图,那么Map[0][n]的值代表 第n号物品的价值,Map[i][j]代表用 j  替代 i 后,物品j的价值.我们认为酋长的承诺为节点 ‘1’ ,则我们需要做的就是通过一系列操作求出Map[0][1]的最小值,这时可以看出 这是一个最短路问题.题目还规定了,等级高的不会同意与等级低的交换,等级低的亦不会和高于自身m个级别的人交换,所以我们先来个简单的预处理:通过枚举1~N所有点作为最小等级,然后标记出所有非法点. 这样一来就是纯粹的最

poj 1062 -- 昂贵的聘礼

昂贵的聘礼 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 35515   Accepted: 10163 Description 年 轻的探险家来到了一个印第安部落里.在那里他和酋长的女儿相爱了,于是便向酋长去求亲.酋长要他用10000个金币作为聘礼才答应把女儿嫁给他.探险家拿 不出这么多金币,便请求酋长降低要求.酋长说:"嗯,如果你能够替我弄到大祭司的皮袄,我可以只要8000金币.如果你能够弄来他的水晶球,那么只要 5

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

题目链接:昂贵的聘礼 这个题对自己收获挺大的,模板要自己经常敲,才能理解,要自己经常敲,从能温故而知新,自己以前总结的建图方式,做题的时候要会用,要敢用,否则==NULL. 题意对于交换条件描述的有点不清楚,这里解释一下,假设8件物品,等级差距不能超过3,酋长LV 5,所以可以进行交换的LV区间是[2,5][3,6][4,7][5,8],不必考虑题目那一句,"但是如果他和某个地位较低的人进行了交易,地位较高的的人不会再和他交易,他们认为这样等于是间接接触,反过来也一样".越看越晕,只要

poj 1062 昂贵的聘礼 (最短路)

poj 1062 昂贵的聘礼 Description 年轻的探险家来到了一个印第安部落里.在那里他和酋长的女儿相爱了,于是便向酋长去求亲.酋长要他用10000个金币作为聘礼才答应把女儿嫁给他.探险家拿不出这么多金币,便请求酋长降低要求.酋长说:"嗯,如果你能够替我弄到大祭司的皮袄,我可以只要8000金币.如果你能够弄来他的水晶球,那么只要5000金币就行了."探险家就跑到大祭司那里,向他要求皮袄或水晶球,大祭司要他用金币来换,或者替他弄来其他的东西,他可以降低价格.探险家于是又跑到其他

POJ - 1062昂贵的聘礼最短路或者DFS

POJ - 1062 昂贵的聘礼 Time Limit: 1000MS   Memory Limit: 10000KB   64bit IO Format: %I64d & %I64u Submit Status Description 年轻的探险家来到了一个印第安部落里.在那里他和酋长的女儿相爱了,于是便向酋长去求亲.酋长要他用10000个金币作为聘礼才答应把女儿嫁给他.探险家拿不出这么多金币,便请求酋长降低要求.酋长说:"嗯,如果你能够替我弄到大祭司的皮袄,我可以只要8000金币.如

POJ 1062 昂贵的聘礼 最短路

Description 年轻的探险家来到了一个印第安部落里.在那里他和酋长的女儿相爱了,于是便向酋长去求亲.酋长要他用10000个金币作为聘礼才答应把女儿嫁给他.探险家拿不出这么多金币,便请求酋长降低要求.酋长说:"嗯,如果你能够替我弄到大祭司的皮袄,我可以只要8000金币.如果你能够弄来他的水晶球,那么只要5000金币就行了."探险家就跑到大祭司那里,向他要求皮袄或水晶球,大祭司要他用金币来换,或者替他弄来其他的东西,他可以降低价格.探险家于是又跑到其他地方,其他人也提出了类似的要求

poj 1062 昂贵的聘礼 解题报告

题目链接:http://poj.org/problem?id=1062 这一题只要想到如何建图,就不太难解决了.假设对于编号为 i 的物品,如果它得到物品 j 后价格从 pricei 降低到 pricej 的话,就用一个cost[i][j] = pricej.也就是从物品 i 到物品 j 连一条有向边.每一个编号的物品都这样处理,然后套用dijk 算法,求出从每个点出发的最短路,最终最小的那个就是答案.考虑到等级限制,别人可以跟酋长接触的前提是这个人的等级在 [ level 酋长-m  ~ le

POJ 1062 昂贵的聘礼(带限制条件的dijkstra)

题目网址:http://poj.org/problem?id=1062 题目: 昂贵的聘礼 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 49916   Accepted: 14961 Description 年轻的探险家来到了一个印第安部落里.在那里他和酋长的女儿相爱了,于是便向酋长去求亲.酋长要他用10000个金币作为聘礼才答应把女儿嫁给他.探险家拿不出这么多金币,便请求酋长降低要求.酋长说:"嗯,如果你能够替我弄到

POJ - 1062 昂贵的聘礼(最短路Dijkstra)

昂贵的聘礼 Time Limit: 1000MS Memory Limit: 10000KB 64bit IO Format: %I64d & %I64u SubmitStatus Description 年轻的探险家来到了一个印第安部落里.在那里他和酋长的女儿相爱了,于是便向酋长去求亲.酋长要他用10000个金币作为聘礼才答应把女儿嫁给他.探险家拿不出这么多金币,便请求酋长降低要求.酋长说:"嗯,如果你能够替我弄到大祭司的皮袄,我可以只要8000金币.如果你能够弄来他的水晶球,那么只要