背景:冒险者想娶国王,啊呸,酋长的女儿。酋长收费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 }