• P2149 [SDOI2009]Elaxia的路线


    题目传送门

    题目描述

    最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间。

    Elaxia和w**每天都要奔波于宿舍和实验室之间,他们 希望在节约时间的前提下,一起走的时间尽可能的长。

    现在已知的是Elaxia和w**所在的宿舍和实验室的编号以及学校的地图:地图上有N个路 口,M条路,经过每条路都需要一定的时间。 具体地说,就是要求无向图中,两对点间最短路的最长公共路径。

    输入输出格式

    输入格式:

    第一行:两个整数N和M(含义如题目描述)。

    第二行:四个整数x1、y1、x2、y2(1 ≤ x1 ≤ N,1 ≤ y1 ≤ N,1 ≤ x2 ≤ N,1 ≤ y2 ≤ N),分别表示Elaxia的宿舍和实验室及w**的宿舍和实验室的标号(两对点分别 x1,y1和x2,y2)。

    接下来M行:每行三个整数,u、v、l(1 ≤ u ≤ N,1 ≤ v ≤ N,1 ≤ l ≤ 10000),表 u和v之间有一条路,经过这条路所需要的时间为l。

    输出格式:

    一行,一个整数,表示每天两人在一起的时间(即最长公共路径的长度)

    输入输出样例

    输入样例#1: 
    9 10
    1 6 7 8
    1 2 1
    2 5 2
    2 3 3
    3 4 2
    3 9 5
    4 5 3
    4 6 4
    4 7 2
    5 8 1
    7 9 1
    输出样例#1: 
    3

    说明

    对于30%的数据,N ≤ 100;

    对于60%的数据,N ≤ 1000;

    对于100%的数据,N ≤ 1500,输入数据保证没有重边和自环。


    这题是我见过最毒瘤的题,没有之一。数组范围真的是太迷了,卡了我一天。

    思路:首先当我们拿到题面时,发现出题人还是蛮友善的,直接把要求的问题写了出来。

       然后我们就要思考如何记录最短路上的路径,我们可以很容易推出,如果有一条从x到y权值为z的边。从起点1到x的最短路+从y到终点1的最短路+z如果等于从起点1到终点1的最短路并且从起点2到x的最短路+从y到终点2的最短路+z也等于从起点2到终点2的最短路,

       就说明这条边是在最短路上的。既然要求最短路的最长公共路径,我们就需要把符合条件的边重新构建出一张有向图,然后跑一边记搜。当然,最短路不止一条。要分别建两次图和记搜两次。(虽然这不符合出题人意图,但也能A)出题人可能没想到这么多


    下面为大家提供两份参考代码,一份用的dijkstra堆优化求得最短路,另一份使用SPFA求最短路

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef pair<int,int> P;
      4 int n,m,x1,x2,yy1,y2,dis[5][50005],f[40005],next[5000005],first[10005],to[5000005],v[5000005],tot;
      5 int ans,book[10005],dp[10005],tot1,next1[5000005],first1[20005],to1[5000005],v1[5000005];
      6 void add(int x,int y,int z)
      7 {
      8     tot++;
      9     next[tot]=first[x];
     10     first[x]=tot;
     11     to[tot]=y;
     12     v[tot]=z;
     13 }
     14 void add2(int x,int y,int z)
     15 {
     16     tot1++;
     17     next1[tot1]=first1[x];
     18     first1[x]=tot1;
     19     to1[tot1]=y;
     20     v1[tot1]=z;
     21     book[x]=book[y]=1;
     22 }
     23 void dijk(int t,int num)
     24 {
     25     priority_queue<P,vector<P>,greater<P> >q;
     26     for(int i=1;i<=n;i++)  f[i]=false;
     27     dis[num][t]=0;
     28     q.push(P(0,t));
     29     while(!q.empty())
     30     {
     31         int x=q.top().second;
     32         q.pop();
     33         if(f[x]==true) continue;
     34         f[x]=true;
     35         for(int i=first[x];i;i=next[i])
     36         {
     37             int y=to[i];
     38             if(dis[num][y]>dis[num][x]+v[i])
     39             {
     40                 dis[num][y]=dis[num][x]+v[i];
     41                 q.push(P(dis[num][y],y));    
     42             } 
     43         }
     44     }
     45 }
     46 void dp1(int x)
     47 {
     48     if(dp[x]!=0) return ;
     49     for(int i=first1[x];i;i=next1[i])
     50     {
     51         int y=to1[i];
     52         dp1(y);
     53         dp[x]=max(dp[x],dp[y]+v1[i]);
     54     }
     55 }
     56 int main()
     57 {
     58     memset(dis,999999,sizeof(dis));
     59     scanf("%d %d
    %d %d %d %d",&n,&m,&x1,&yy1,&x2,&y2);
     60     for(int i=1;i<=m;i++)
     61     {
     62         int xx,yy,zz;
     63         scanf("%d %d %d",&xx,&yy,&zz);
     64         add(xx,yy,zz);
     65         add(yy,xx,zz);
     66     }
     67     dijk(x1,1);
     68     dijk(x2,2);
     69     dijk(yy1,3);
     70     dijk(y2,4);
     71     for(int i=1;i<=n;i++)
     72     {
     73         for(int j=first[i];j;j=next[j])
     74         {
     75             int y=to[j];
     76             if(dis[1][i]+dis[3][y]+v[j]==dis[1][yy1])
     77             {
     78                 if(dis[4][i]+dis[2][y]+v[j]==dis[2][y2])  add2(y,i,v[j]);
     79             }
     80         }
     81     }
     82     for(int i=1;i<=n;i++) if(!dp[i]&&book[i]) dp1(i);
     83     for(int i=1;i<=n;i++) ans=max(ans,dp[i]);
     84     memset(dp,0,sizeof(dp));
     85     memset(first1,0,sizeof(first1));
     86     memset(next1,0,sizeof(next1));
     87     memset(to1,0,sizeof(to1));
     88     memset(v1,0,sizeof(v1));
     89     tot1=0;
     90     for(int i=1;i<=n;i++)
     91     {
     92         for(int j=first[i];j;j=next[j])
     93         {
     94             int y=to[j];
     95             if(dis[1][i]+dis[3][y]+v[j]==dis[1][yy1])
     96             {
     97                    if(dis[2][i]+dis[4][y]+v[j]==dis[2][y2])  add2(i,y,v[j]);
     98             }
     99         }
    100     }
    101     for(int i=1;i<=n;i++) if(!dp[i]&&book[i]) dp1(i);
    102     for(int i=1;i<=n;i++) ans=max(ans,dp[i]);
    103     printf("%d",ans);
    104     return 0;
    105 } 
    dijkstra堆优化
      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef pair<int,int> P;
      4 int n,m,x1,x2,yy1,y2,dis[5][50005],f[40005],next[5000005],first[10005],to[5000005],v[5000005],tot;
      5 int ans,book[10005],dp[10005],tot1,next1[5000005],first1[20005],to1[5000005],v1[5000005];
      6 void add(int x,int y,int z)
      7 {
      8     tot++;
      9     next[tot]=first[x];
     10     first[x]=tot;
     11     to[tot]=y;
     12     v[tot]=z;
     13 }
     14 void add2(int x,int y,int z)
     15 {
     16     tot1++;
     17     next1[tot1]=first1[x];
     18     first1[x]=tot1;
     19     to1[tot1]=y;
     20     v1[tot1]=z;
     21     book[x]=book[y]=1;
     22 }
     23 void spfa(int t,int num)
     24 {
     25     queue<int>q;
     26     for(int i=1;i<=n;i++)  f[i]=false;
     27     dis[num][t]=0;
     28     q.push(t);
     29     f[t]=true;
     30     while(!q.empty())
     31     {
     32         int x=q.front();
     33         q.pop();
     34         f[x]=false;
     35         for(int i=first[x];i;i=next[i])
     36         {
     37             int y=to[i];
     38             if(dis[num][y]>dis[num][x]+v[i])
     39             {
     40                 dis[num][y]=dis[num][x]+v[i];
     41                 if(f[y]==false)
     42                 {
     43                     q.push(y);
     44                     f[y]=true;
     45                 }
     46                     
     47             } 
     48         }
     49     }
     50 }
     51 void dp1(int x)
     52 {
     53     if(dp[x]!=0) return ;
     54     for(int i=first1[x];i;i=next1[i])
     55     {
     56         int y=to1[i];
     57         dp1(y);
     58         dp[x]=max(dp[x],dp[y]+v1[i]);
     59     }
     60 }
     61 int main()
     62 {
     63     memset(dis,999999,sizeof(dis));
     64     scanf("%d %d
    %d %d %d %d",&n,&m,&x1,&yy1,&x2,&y2);
     65     for(int i=1;i<=m;i++)
     66     {
     67         int xx,yy,zz;
     68         scanf("%d %d %d",&xx,&yy,&zz);
     69         add(xx,yy,zz);
     70         add(yy,xx,zz);
     71     }
     72     spfa(x1,1);
     73     spfa(x2,2);
     74     spfa(yy1,3);
     75     spfa(y2,4);
     76     for(int i=1;i<=n;i++)
     77     {
     78         for(int j=first[i];j;j=next[j])
     79         {
     80             int y=to[j];
     81             if(dis[1][i]+dis[3][y]+v[j]==dis[1][yy1])
     82             {
     83                 if(dis[4][i]+dis[2][y]+v[j]==dis[2][y2])  add2(y,i,v[j]);
     84             }
     85         }
     86     }
     87     for(int i=1;i<=n;i++) if(!dp[i]&&book[i]) dp1(i);
     88     for(int i=1;i<=n;i++) ans=max(ans,dp[i]);
     89     memset(dp,0,sizeof(dp));
     90     memset(first1,0,sizeof(first1));
     91     memset(next1,0,sizeof(next1));
     92     memset(to1,0,sizeof(to1));
     93     memset(v1,0,sizeof(v1));
     94     tot1=0;
     95     for(int i=1;i<=n;i++)
     96     {
     97         for(int j=first[i];j;j=next[j])
     98         {
     99             int y=to[j];
    100             if(dis[1][i]+dis[3][y]+v[j]==dis[1][yy1])
    101             {
    102                    if(dis[2][i]+dis[4][y]+v[j]==dis[2][y2])  add2(i,y,v[j]);
    103             }
    104         }
    105     }
    106     for(int i=1;i<=n;i++) if(!dp[i]&&book[i]) dp1(i);
    107     for(int i=1;i<=n;i++) ans=max(ans,dp[i]);
    108     printf("%d",ans);
    109     return 0;
    110 } 
    SPFA
  • 相关阅读:
    JAVA访问权限控制[zhuan]
    Netstat简介
    查看cpu性能和磁盘空间
    简单linux查询
    linux 三剑客命令(grep,sed ,awk)
    同步、异步的使用场景及好处
    AJAX中同步和异步的区别和使用场景
    在SpringBoot中用SpringAOP实现日志记录功能
    springboot使用@Aspect实现AOP记录日志讲解
    Spring:获取容器中的Bean
  • 原文地址:https://www.cnblogs.com/jiuduSHENBENG/p/11216054.html
Copyright © 2020-2023  润新知