zoukankan      html  css  js  c++  java
  • P1073 最优贸易

    最优贸易

    洛谷链接

    这道题是09年提高组的第三题。

    题目大意:

    有个商人在一个图上走,图上的点有权值,各个点之间有边相连,求出在商人可以到达终点的条件下,所经历的点的最小权值与最大权值的差(每个点或边可以走多次)。

    这个题有两种做法:

    1.

    用两遍dfs,一遍求出点的min,另一边求出点的max,最后两个数组相减,找出最大值,得出答案。

    代码:

     1 #include<queue>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<iostream>
     5 using namespace std;
     6 int n,m;
     7 int num_edge1,num_edge2;
     8 int ans;
     9 int a[100001];
    10 int    maxx[100001],minn[100001],head1[100001],head2[100001];
    11 int x,y,z;
    12 struct hehe{
    13     int next;
    14     int to;
    15 };
    16 hehe edge1[1000001],edge2[1000001];
    17 inline void add_edge1(int from,int to){
    18     edge1[++num_edge1].next=head1[from];
    19     edge1[num_edge1].to=to;
    20     head1[from]=num_edge1;
    21 }
    22 inline void add_edge2(int from,int to){
    23     edge2[++num_edge2].next=head2[from];
    24     edge2[num_edge2].to=to;
    25     head2[from]=num_edge2;
    26 }
    27 inline void dfs2(int u,int k){
    28     int i,v;
    29     maxx[u]=max(maxx[u],k);
    30     for(i=head2[u];i!=-1;i=edge2[i].next){
    31         v=edge2[i].to;
    32         if(maxx[v]<k)dfs2(v,max(k,a[v]));
    33     }
    34 }
    35 inline void dfs1(int u,int k){
    36     int v;
    37     minn[u]=min(minn[u],k);
    38     for(int i=head1[u];i!=-1;i=edge1[i].next){ 
    39         v=edge1[i].to;
    40         if(minn[v]>k)
    41             dfs1(v,min(k,a[v]));
    42     }
    43 }
    44 int main(){
    45     memset(head1,-1,sizeof(head1));
    46     memset(head2,-1,sizeof(head2));
    47     scanf("%d%d",&n,&m);
    48     for(int i=1;i<=n;i++){
    49         scanf("%d",&a[i]);
    50         maxx[i]=-4200000; 
    51         minn[i]=4200000;
    52     }
    53     for(int i=1;i<=m;i++){
    54         scanf("%d%d%d",&x,&y,&z);
    55         if(z==2){ 
    56             add_edge1(x,y); 
    57             add_edge1(y,x);
    58             add_edge2(x,y);
    59             add_edge2(y,x);
    60         }
    61         else{
    62             add_edge1(x,y);
    63             add_edge2(y,x);
    64         }
    65     }
    66     dfs1(1,a[1]);
    67     dfs2(n,a[n]);
    68     for(int i=1;i<=n;i++)
    69         ans=max(ans,maxx[i]-minn[i]);
    70     printf("%d",ans);
    71     return 0;
    72 }
    View Code

    2.

    先用dfs求出可以到达根节点的节点,之后一遍spfa,求出到该节点时,可以走到的最小的权值是多少,最后找出最大值,得到答案。

    代码:

     1 #include<queue>
     2 #include<cstdio>
     3 #define N 100010
     4 #define M 1000010
     5 using namespace std;
     6 queue<int>p;
     7 int next1[M],to1[M],num1,head1[N];
     8 int next2[M],to2[M],num2,head2[N];
     9 int a,b,c,d[N],dis[N],n,m,u,ans=-1;
    10 bool boo[N],exist[N];
    11 void add1(int false_from,int false_to){
    12     next1[++num1]=head1[false_from];
    13     to1[num1]=false_to;
    14     head1[false_from]=num1;
    15 }
    16 void add2(int false_from,int false_to){
    17     next2[++num2]=head2[false_from];
    18     to2[num2]=false_to;
    19     head2[false_from]=num2;
    20 }
    21 void dfs(int x){
    22     boo[x]=1;
    23     for(int i=head2[x];i;i=next2[i]){
    24         if(!boo[to2[i]])
    25             dfs(to2[i]);
    26     }
    27 }
    28 void spfa(){
    29     for(int i=1;i<=n;++i)
    30         dis[i]=42000000;
    31     p.push(1);
    32     exist[1]=1;
    33     while(!p.empty()){
    34         u=p.front();
    35         p.pop();
    36         exist[u]=0;
    37         for(int i=head1[u];i;i=next1[i])
    38             if(dis[to1[i]]>min(dis[u],d[to1[i]])&&boo[to1[i]]){
    39                 dis[to1[i]]=min(dis[u],d[to1[i]]);
    40                 if(!exist[to1[i]]){
    41                     p.push(to1[i]);
    42                     exist[to1[i]]=1;
    43                 }
    44             }
    45     }
    46 }
    47 int main(){
    48     scanf("%d%d",&n,&m);
    49     for(int i=1;i<=n;++i)
    50         scanf("%d",&d[i]);
    51     for(int i=1;i<=m;++i){
    52         scanf("%d%d%d",&a,&b,&c);
    53         if(c==1){
    54             add1(a,b);
    55             add2(b,a);
    56         }
    57         else{
    58             add1(a,b);
    59             add1(b,a);
    60             add2(b,a);
    61             add2(a,b);
    62         }
    63     }
    64     dfs(n);
    65     spfa();
    66     for(int i=1;i<=n;++i)
    67         ans=max(ans,d[i]-dis[i]);
    68     printf("%d",ans);
    69     return 0;
    70 }
    View Code

    其实个人感觉这两种做法差不多。

  • 相关阅读:
    257. Binary Tree Paths
    324. Wiggle Sort II
    315. Count of Smaller Numbers After Self
    350. Intersection of Two Arrays II
    295. Find Median from Data Stream
    289. Game of Life
    287. Find the Duplicate Number
    279. Perfect Squares
    384. Shuffle an Array
    E
  • 原文地址:https://www.cnblogs.com/jsawz/p/6829077.html
Copyright © 2011-2022 走看看