POJ少有的中文题 (很久之前就想写来着,但是原来不会啊…..)
思路:
首先我们可以新建一个点,从这个点向每个物品连一条权值为这个物品价值的边 (这样就把点权转化成了边权对吧……)
我们已经知道了一个物品的替代品是啥,那么就可以从每个替代品向这个物品连一条边权为替代品价值的边。
是不是很有道理。。。
随后枚举区间 (区间里得包括酋长的地位)
每次枚举从新建的点向一号点跑一遍Dijkstra就OK了。
//By SiriusRen
#include <queue>
#include <cstdio>
#include <cstring>
#define N 100050
using namespace std;
int n,m,xx,yy,zz,ww,vis[105],d[105],answer=0x3fffffff;
int tot=0,first[105],next[N],v[N],w[N],p[105];
void add(int from,int to,int weight){
v[tot]=to;w[tot]=weight;
next[tot]=first[from];first[from]=tot++;
}
struct Node{int position,weight;}top,jy;
bool operator < (Node a,Node b){
return a.weight>b.weight;
}
priority_queue<Node>pq;
int main(){
scanf("%d%d",&m,&n);
memset(first,-1,sizeof(first));
for(int i=1;i<=n;i++){
scanf("%d%d%d",&xx,&p[i],&zz);
add(0,i,xx);
while(zz--){
scanf("%d%d",&xx,&ww);
add(xx,i,ww);
}
}
for(int T=-m;T<=0;T++){
memset(d,0x3f,sizeof(d));
memset(vis,0,sizeof(vis));
xx=p[1]+T;yy=p[1]+T+m;
d[0]=jy.position=0,jy.weight=0;pq.push(jy);
while(!pq.empty()){
top=pq.top();pq.pop();
if(vis[top.position])continue;
vis[top.position]=1;
for(int i=first[top.position];~i;i=next[i])
{
if(d[v[i]]>d[top.position]+w[i]&&!vis[v[i]]&&p[v[i]]>=xx&&p[v[i]]<=yy)
{
d[v[i]]=d[top.position]+w[i];
jy.position=v[i];
jy.weight=top.weight+w[i];
pq.push(jy);
}
}
}
answer=min(answer,d[1]);
}
printf("%d\n",answer);
}