题目链接: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 }
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 ",maxx); 73 return 0; 74 }