POJ 1062 昂贵的聘礼 (约束最短路)

  • 题意: 有向图,每个点代表一个物品(有价格,级别),边代表从当前点转移到目的点的价格,问买到1点的最小价格,路径上点的级别差不能超过m
  • 思路: 不考虑级别则通过 d[y] > d[x]+cost[x][y]-a[x]+a[y] 价格转移,正向存边求1到所有点的最短路即可.
    考虑级别差,当级别差为0时代表没有级别差,然后需要枚举最大级别跑n边最短路 lv-lev[u]>m || lev[u]>lv || abs(lev[u]-lev[s])>m 表示不符合当前约束
    经过观察POJ讨论版的上的数据,感觉实际可以表示为一个DAG,然后通过DP来做
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define ll long long
#define FOR(i,l,r) for(int i = l ; i <= r ;++i )
#define inf 1<<30
#define EPS (1e-9)
#define ALL(T)  T.begin(),T.end()
#define lson(i)     i<<1
#define rson(i)     (i<<1|1)
using namespace std;
typedef pair<int,int> pii;

const int maxn = 110,maxm =10110;
struct Edge{
    int to,next,cost;
}edge[maxm];
int head[maxn],tot;
int d[maxn],v[maxn];
int a[maxn],lev[maxn];
int n,m,s;

void addEdge(int u,int v,int w){
    edge[++tot].to = v;
    edge[tot].cost = w;
    edge[tot].next = head[u];
    head[u] = tot;
}
void init(){
    memset(head,0,sizeof(head));
    tot = 0;
}

int spfa(int s,int lv){
    queue<int> q;
    FOR(i,1,n){
        v[i] = 0;
        d[i]=a[i]+a[s];
    }
    d[s]-=a[s];
    q.push(s);
    while(q.size()){
        int x= q.front();   q.pop();
        v[x] = 0;
        for(int i=head[x];i;i=edge[i].next){
            int y = edge[i].to;
            if(lv-lev[y]>m || lev[y]>lv || abs(lev[y]-lev[s])>m)
                continue;
            int z = edge[i].cost;
            if( d[y] > d[x]+z-a[x]+a[y]){
                d[y] = d[x]+z-a[x]+a[y];
                if(v[y]==0){
                    q.push(y);
                    v[y] = 1;
                }
            }
        }
    }
    int mi = inf;
    FOR(i,1,n)  mi = min(mi,d[i]);
    return mi;
} 

int dij(int s,int lv){
    priority_queue<pii,vector<pii>,greater<pii> > que;
    FOR(i,1,n){
        d[i]=a[i]+a[s];
    }
    d[s]-=a[s];
    que.push(pii(d[s],s));
    while(!que.empty()){
        pii p = que.top();  que.pop();
        int v = p.second;
        if(d[v]<p.first)    continue;
        for(int i=head[v];i;i=edge[i].next){
            int u = edge[i].to;
            if(lv-lev[u]>m || lev[u]>lv || abs(lev[u]-lev[s])>m)
                continue;
            if( d[u] > d[v]+edge[i].cost-a[v]+a[u]){
                d[u] = d[v]+edge[i].cost-a[v]+a[u];
                que.push(pii(d[u],u));
            }
        }
    }
    int mi = inf;
    FOR(i,1,n)  mi = min(mi,d[i]);
    return mi;
}
int main(){
    while(cin >> m >> n){
    if(m==0)    m = 110;
    int k,fr,weight;
    init();
    FOR(i,1,n){
        cin >> a[i] >> lev[i] >>k;
        FOR(j,1,k){
            cin >>fr >> weight;
            addEdge(i,fr,weight);
        }
    }
    int ans = inf;
    FOR(i,1,n){
        if((lev[i]-lev[1])<=m)
            // ans = min(ans,spfa(1,lev[i]));
            ans = min(ans,dij(1,lev[i]));
    }
    cout << ans <<endl;
    }
    return 0;
}

spfa和dijkstra都是47ms,没什么差别

题目连接

猜你喜欢

转载自www.cnblogs.com/xxrlz/p/11281088.html