• 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,没什么差别

    题目连接

  • 相关阅读:
    Redis未授权访问攻击过程与防范
    Redis安装
    Connection closing...Socket close. Connection closed by foreign host. Disconnected from remote host(centos6.9) at 14:59:05.
    windows远程xshell文件上传下载:
    Linux重置MySQL密码
    nginx rewrite 实现URL跳转
    Openstack 清除openstack网络与路由 (十七)
    创建 OpenStack云主机 (十五)
    OpenStack 存储服务 Cinder存储节点部署LVM (十四)
    OpenStack 存储服务 Cinder介绍和控制节点部署 (十三)
  • 原文地址:https://www.cnblogs.com/xxrlz/p/11281088.html
Copyright © 2020-2023  润新知