GYM101635E Ingredients

题目链接:https://vjudge.net/problem/Gym-101635E

题目大意:

  给定一个有 \(N\) 条边的有向无环图(有多个起点),每条边都有其费用和收益,现要从一个或多个起点出发,以某一个或多个点为终点(一个点不能多次作为终点;如果有多个方案能到达同一个点,则选择总费用最少的),问在使得总费用不超过 \(B\) 的大前提下,能得到的最大收益(如果有多个得到最大收益的方法,则选择使得费用最少的)。输出最大收益及其对应的总费用。

  (建议仔细地读一下 \(Important Notes\))

知识点:  DP、最短路

解题思路:

  先用 \(Dijkstra\) 跑出从各个起点到各个点的最小费用及其对应的收益(如果有多个费用最小的方案,则选择收益最大的那个),再用 \(dp\) 计算出在各个总费用下所能得到的最大收益。

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxm = 1000000+5, maxn = 10000+5, inf=0x3f3f3f3f;
 4 
 5 struct Edge{
 6     int to,nxt,cost,prestige;
 7 }edge[maxm];
 8 int head[maxm],tot;
 9 void init(){
10     memset(head,-1,sizeof(head));
11     tot=0;
12 }
13 void addedge(int u,int v,int cost,int pres){
14     edge[tot].to=v;
15     edge[tot].nxt=head[u];
16     edge[tot].prestige=pres;
17     edge[tot].cost=cost;
18     head[u]=tot++;
19 }
20 
21 int min_cost[maxn],max_pres[maxn];
22 bool noroot[maxn];
23 map<string,int> ind;
24 
25 void dijkstra(int s){
26     queue<int> que;
27     que.push(s);
28     min_cost[s]=max_pres[s]=0;
29     while(!que.empty()){
30         int v=que.front();
31         que.pop();
32         for(int i=head[v];i!=-1;i=edge[i].nxt){
33             int to=edge[i].to;
34             if(min_cost[to]>min_cost[v]+edge[i].cost){
35                 min_cost[to]=min_cost[v]+edge[i].cost;
36                 max_pres[to]=max_pres[v]+edge[i].prestige;
37                 que.push(to);
38             }
39             else if(min_cost[to]==min_cost[v]+edge[i].cost&&max_pres[to]<max_pres[v]+edge[i].prestige){
40                 max_pres[to]=max_pres[v]+edge[i].prestige;
41                 que.push(to);
42             }
43         }
44     }
45 }
46 int dp[maxn];
47 int main(){
48     std::ios::sync_with_stdio(false);   //如果没有加速输入输出的话会T
49     int B,N,cos,pre,u,v;
50     int cnt=1;
51     string to,from,tmp;
52     cin>>B>>N;
53     init();
54     for(int i=0;i<N;i++){
55         cin>>to>>from>>tmp>>cos>>pre;
56         if(!ind[to])
57             ind[to]=cnt++;
58         v=ind[to];
59         if(!ind[from])
60             ind[from]=cnt++;
61         u=ind[from];
62         addedge(u,v,cos,pre);
63         noroot[v]=true;
64     }
65     for(int i=1;i<cnt;i++)
66         min_cost[i]=inf,max_pres[i]=0;
67     for(int i=1;i<cnt;i++){
68         if(!noroot[i])
69             dijkstra(i);
70     }
71     dp[0]=0;
72     for(int i=1;i<cnt;i++){
73         for(int j=B;j>=min_cost[i];j--)
74             dp[j]=max(dp[j],dp[j-min_cost[i]]+max_pres[i]);
75     }
76     int ans1=0,ans2=0;
77     for(int i=0;i<=B;i++){
78         if(dp[i]>ans1)
79             ans1=dp[i],ans2=i;
80     }
81     cout<<ans1<<endl;
82     cout<<ans2<<endl;
83 
84     return 0;
85 }

 

posted @ 2018-03-18 16:11  Blogggggg  阅读(391)  评论(0编辑  收藏  举报