poj1062 [ZJOI2002]昂贵的聘礼(spfa+枚举)

来源:互联网 发布:2016淘宝开店步骤 编辑:程序博客网 时间:2024/05/17 03:10

思路见神犇http://gisyhy.blog.163.com/blog/static/12939034320099883715624/
这题比较麻烦的地方在于等级限制,让我们很不好下手,突破口:1一定在最短路上,所以区间最大为[lev[1]-m,lev[1]+m],但是这样还不满足每两个点的等级之差均在m以内,因此我们枚举[lev[1]-m,lev[1] ],[lev[1]-m+1,lev[1]+1]…[lev[1],lev[1]+m]区间,这些区间内的点一定满足题意,我们用这些点建图,跑spfa。

#include <cstdio>#include <cstring>#include <algorithm>#include <queue>using namespace std;#define ll long long#define inf 0x3f3f3f3f#define N 105inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}int m,n,a[N],d[N],lev[N],h[N],num=0;bool inq[N];struct edge{    int to,next,v;}data[N*N];int spfa(int s,int t){    memset(d,0x3f,sizeof(d));    queue<int>q;    q.push(1);d[1]=0;inq[1]=1;    while(!q.empty()){        int x=q.front();inq[x]=0;q.pop();        for(int i=h[x];i;i=data[i].next){            int y=data[i].to;            if(lev[y]<s||lev[y]>t) continue;            if(d[x]+data[i].v<d[y]){                d[y]=d[x]+data[i].v;                if(!inq[y]) inq[y]=1,q.push(y);            }        }    }int res=inf;    for(int i=1;i<=n;++i)        res=min(res,d[i]+a[i]);    return res;}int main(){//  freopen("a.in","r",stdin);    m=read();n=read();    for(int i=1;i<=n;++i){        a[i]=read();lev[i]=read();int nn=read();        while(nn--){//i->x            int x=read(),v=read();            data[++num].to=x;data[num].next=h[i];h[i]=num;data[num].v=v;        }    }int ans=inf;    for(int i=lev[1]-m;i<=lev[1];++i)//枚举lev区间         ans=min(ans,spfa(i,i+m));    printf("%d\n",ans);    return 0;}
原创粉丝点击