洛谷 P1073 最优贸易(DFS+DP||SPFA)

题目链接:https://www.luogu.com.cn/problem/P1073

 

DFS+DP:

设f[i][0/1],

f[i][0]表示走到i点的最小价格,f[i][1]表示走到i点的最大收益(差值)。转移过于简单。

注意DFS中的剪枝。

 

AC代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 using namespace std;
 5 const int N=100005;
 6 int n,m,tot;
 7 int head[N],a[N],f[N][2];
 8 struct node{
 9     int to,next;
10 }edge[N*10];
11 void add(int u,int v){
12     edge[tot].to=v;
13     edge[tot].next=head[u];
14     head[u]=tot++;
15 }
16 void DFS(int u,int minn,int pre){
17     int flag=1;
18     minn=min(minn,a[u]);
19     if(minn<f[u][0]) f[u][0]=minn,flag=0;
20     int maxn=max(f[pre][1],a[u]-minn);
21     if(f[u][1]<maxn) f[u][1]=maxn,flag=0;
22     if(flag) return;
23     for(int i=head[u];i!=-1;i=edge[i].next){
24         int v=edge[i].to;
25         DFS(v,minn,u);
26     }
27 }
28 int main(){
29     memset(head,-1,sizeof(head));
30     scanf("%d%d",&n,&m);
31     for(int i=1;i<=n;i++) f[i][0]=0x7f7f7f;
32     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
33     for(int i=1;i<=m;i++){
34         int x,y,z;
35         scanf("%d%d%d",&x,&y,&z);
36         add(x,y);
37         if(z==2) add(y,x);
38     }
39     DFS(1,0x7f7f7f,0);
40     printf("%d",f[n][1]);
41     return 0;
42 }
AC代码

 

SPFA:

正向建图,然后反向建图。在正向图中dis[i]表示从1到i号点经过的最小点权为多少。在反向图中dis1[i]表示从n到i号点经过的最大边权是多少。ans=max(dis1[i]-dis[i]),1<=i<=n。

记录最大、小边权只需要在原来的SPFA的基础上改一下即可。

 

AC代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<queue> 
 4 #include<cstring>
 5 using namespace std;
 6 const int N=100005;
 7 int n,m,tot,cnt;
 8 struct node{
 9     int to,next;
10 }edge[N*10];
11 struct node1{
12     int to,next;
13 }edge1[N*10];
14 int head[N],head1[N],dis[N],dis1[N],a[N],maxx,vis[N];
15 void add(int u,int v){
16     edge[tot].to=v;
17     edge[tot].next=head[u];
18     head[u]=tot++;
19 }
20 void add1(int u,int v){
21     edge1[cnt].to=v;
22     edge1[cnt].next=head1[u];
23     head1[u]=cnt++;
24 }
25 void SPFA(int u){
26     queue<int> q;
27     q.push(u); dis[u]=a[u]; vis[u]=1;
28     while(!q.empty()){
29         int u=q.front(); q.pop(); vis[u]=0;
30         for(int i=head[u];i!=-1;i=edge[i].next){
31             int v=edge[i].to;
32             int minn=min(dis[u],a[v]); 
33             if(dis[v]>minn){
34                 dis[v]=minn;
35                 if(!vis[v]) q.push(v),vis[v]=1;
36             }
37         }
38     }
39 }
40 void SPFA1(int u){
41     queue<int> q;
42     memset(vis,0,sizeof(vis));
43     q.push(u); dis1[u]=a[u]; vis[u]=1;
44     while(!q.empty()){
45         int u=q.front(); q.pop(); vis[u]=0;
46         for(int i=head1[u];i!=-1;i=edge1[i].next){
47             int v=edge1[i].to;
48             int maxn=max(dis1[u],a[v]); 
49             if(dis1[v]<maxn){
50                 dis1[v]=maxn;
51                 if(!vis[v]) q.push(v),vis[v]=1;
52             }
53         }
54     }
55 }
56 int main(){
57     memset(head,-1,sizeof(head));
58     memset(head1,-1,sizeof(head1));
59     memset(dis,0x7f7f7f,sizeof(dis));
60     scanf("%d%d",&n,&m);
61     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
62     for(int i=1;i<=m;i++){
63         int x,y,z;
64         scanf("%d%d%d",&x,&y,&z);
65         add(x,y); add1(y,x);
66         if(z==2) add(y,x),add1(x,y);
67     }
68     SPFA(1);
69     memset(dis1,-1,sizeof(dis1)); 
70     SPFA1(n);
71     for(int i=1;i<=n;i++) maxx=max(maxx,dis1[i]-dis[i]);
72     printf("%d\n",maxx);
73     return 0;
74 }
AC代码

 

posted @ 2020-10-29 22:30  dfydn  阅读(75)  评论(0编辑  收藏  举报