POJ-1062 昂贵的聘礼

Posted on 2021-11-22 22:17  Capterlliar  阅读(16)  评论(0编辑  收藏  举报

传送门

背景:冒险者想娶国王,啊呸,酋长的女儿。酋长收费p[1]元,但他接受用物品来代替金币。物品在部落的人手里,部落居民也要收费,但也接受以物易物。这个部落的人还有个毛病,不接受地位和自己相差d的人的东西,间接交易也不行。求冒险者娶到酋长女儿的最小花费。哦对了,这个部落地位最高的不一定是他们酋长。(酋长好失败(讲真这题做完我觉得我在娶酋长而不是他女儿

翻译过程:最开始也是最直接的想法是以酋长为起点,dfs显然会超时,bfs很难处理地位差的问题。于是考虑倒过来,从每个人开始逆向走,dis[i]为他们所持物品的原始价格,和打折物品连边,边权为折扣价,求走到酋长的最短路,过程中处理低位差不超过d。

然后WA了。仔细思考了一下每个人接受的范围为[l[i]-d,l[i]+d],但题目要求是所有交易地位差不超过d,于是它假了。

草率的思考过后决定将每个人作为地位最低者,向上和地位不超过d的人交换,显然还是假的。或者说地位在bfs的过程中处理就会假掉。

好在终点是确定的,l[1]一定出现在交易中(冒险者不累也不移情别恋),于是枚举每个包含l[1]的区间进行dijk是靠谱的。

然后新的问题出现了,这题起点不确定,还需要枚举每个人,但这个过程可以写得优美一点。设一个虚点,所有人对它连边,边权为初始价格,很好现在初始价格也可以放到边里了非常整齐,然后整整齐齐地跑最短路,over。

聘礼真昂贵啊价值好几发WA呢

代码:

 1 #include<stdio.h>
 2 #include <algorithm>
 3 #include <queue>
 4 using namespace std;
 5 #define ll long long
 6 #define maxx 3005
 7 #define inf 0x7fffffff
 8 //#define int long long
 9 struct edge{
10     int u,v,w;
11     int nxt;
12 }e[maxx*2];
13 int head[maxx]={0},cnt=0;
14 void add(int u,int v,int w){
15     e[++cnt].u=u;
16     e[cnt].v=v;
17     e[cnt].w=w;
18     e[cnt].nxt=head[u];
19     head[u]=cnt;
20 }
21 int n,d,w[maxx],l[maxx];
22 int dis[maxx],vis[maxx];
23 int dijk(int down,int up){
24     for(int i=0;i<=n;i++)
25         dis[i]=inf,vis[i]=0;
26     priority_queue<pair<int,int> > q;
27     dis[0]=0;
28     q.push(make_pair(0,0));
29     while(!q.empty()){
30         int now=q.top().second;
31         q.pop();
32         if(vis[now])
33             continue;
34         vis[now]=1;
35         for(int i=head[now];i;i=e[i].nxt){
36             int to=e[i].v;
37             int f=dis[now]+e[i].w;
38             if(f<dis[to]&&l[to]>=down&&l[to]<=up&&!vis[to]){
39                 dis[to]=f;
40                 q.push(make_pair(-dis[to],to));
41             }
42         }
43     }
44     return dis[1];
45 }
46 signed main() {
47     scanf("%d%d",&d,&n);
48     for(int i=1;i<=n;i++){
49         int v,e,m;
50         scanf("%d%d%d",&v,&e,&m);
51         w[i]=v;l[i]=e;
52         add(0,i,w[i]);
53         for(int j=0;j<m;j++){
54             int k,r;
55             scanf("%d%d",&k,&r);
56             add(k,i,r);
57         }
58     }
59     int ans=inf;
60     for(int i=l[1]-d;i<=l[1];i++){
61         ans=min(ans,dijk(i,i+d));
62     }
63     printf("%d\n",ans);
64     return 0;
65 }
View Code