D67 最短路+区间约束 Dijkstra 算法 U262078 昂贵的聘礼
D67 最短路+区间约束 Dijkstra 算法 U262078 昂贵的聘礼_哔哩哔哩_bilibili
思路
建图技巧:
把物品看做点,分两类连边:
- 直接购买物品 $i$: 从虚拟源点 0 向 $i$ 连边
- 用替代品 $t$ 替代物品 $i$:从 $t$ 向 $i$ 连边

区间约束:
“地位差距超过一定限制的两个人之间不会进行任何形式的直接接触,包括交易。”
在 Dijkstra 中增加约束条件:$L[v]>=y1 \;\&\&\; L[v]<=y2$
注意:存在比酋长地位等级高的人,所以枚举范围为 $L[1]-m,L[1]+m$
相关板子:
D02【模板】最短路 Dijkstra 算法 P4779 单源最短路径 - 董晓 - 博客园
// 最短路+区间约束 Dijkstra 算法 O(n^3*logn) #include<bits/stdc++.h> #define pii pair<int,int> using namespace std; const int N=110,M=10010; int h[N],to[M],w[M],ne[M],idx; int n,m,L[N],d[N]; void add(int a,int b,int c){ to[++idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx; } int dijkstra(int y1,int y2){ memset(d,0x3f,sizeof d); priority_queue<pii,vector<pii>,greater<pii> > q; //小根堆 q.emplace(d[0]=0,0); //从源点0开始 while(q.size()){ auto [dd,u]=q.top(); q.pop(); if(dd>d[u]) continue; //这个u不是第一次出队,不拓展 for(int i=h[u]; i; i=ne[i]){ int v=to[i]; if(L[v]>=y1 && L[v]<=y2){ //区间约束 if(d[v]>d[u]+w[i]){ q.emplace(d[v]=d[u]+w[i],v); } } } } return d[1]; } int main(){ cin>>m>>n; //地位等级差距限制、物品总数 for(int i=1,p,x,t,v; i<=n; i++){ cin>>p>>L[i]>>x; //物品的价格、主人的地位等级、替代品总数 add(0,i,p); //直接购买物品i: 虚拟源点 0 向 i 连边 for(int j=1; j<=x; j++){ cin>>t>>v; add(t,i,v); //用替代品t替代物品i:从 t 向 i 连边 } } int ans=1e9; for(int i=L[1]-m; i<=L[1]; i++) //包含L[1]的等距区间枚举 ans=min(ans,dijkstra(i,i+m)); //区间约束的 Dijkstra cout<<ans; }
浙公网安备 33010602011771号