zoukankan      html  css  js  c++  java
  • BZOJ1880:[SDOI2009]Elaxia的路线(最短路,拓扑排序)

    Description

    最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间。Elaxia和w**每天都要奔波于宿舍和实验室之间,他们 希望在节约时间的前提下,一起走的时间尽可能的长。 现在已知的是Elaxia和w**所在的宿舍和实验室的编号以及学校的地图:地图上有N个路 口,M条路,经过每条路都需要一定的时间。 具体地说,就是要求无向图中,两对点间最短路的最长公共路径。

    Input

    第一行:两个整数N和M(含义如题目描述)。 第二行:四个整数x1、y1、x2、y2(1 ≤ x1 ≤ N,1 ≤ y1 ≤ N,1 ≤ x2 ≤ N,1 ≤ ≤ N),分别表示Elaxia的宿舍和实验室及w**的宿舍和实验室的标号(两对点分别 x1,y1和x2,y2)。 接下来M行:每行三个整数,u、v、l(1 ≤ u ≤ N,1 ≤ v ≤ N,1 ≤ l ≤ 10000),表 u和v之间有一条路,经过这条路所需要的时间为l。 出出出格格格式式式::: 一行,一个整数,表示每天两人在一起的时间(即最长公共路径的长度)。

    Output

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

    Sample Input

    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

    Sample Output

    3

    HINT

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

    Solution

    数组开小了WA,开大了MLE……emmm
    四个点每个点spfa各跑一边最短路,
    然后选定以一个人为标准重新建图
    怎么建呢?枚举每个边,判断其在不在最短路内就好了
    做题的时候忘了很不应该,CF的时候还做过一个类似的判断边是否在最短路上的题
    注意要建单向边
    然后拓扑排序求最长链,那么这个链就是两人最短路的最长相交了。

    Code

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<queue>
      5 #define N (1500+10)
      6 #define M (500000+10)
      7 using namespace std;
      8 struct node
      9 {
     10     int to,next,len;
     11 } edge[M*2];
     12 int head[N],num_edge;
     13 int n,m,x1,x2,y1,y2,len,p,ans;
     14 int u[M],v[M],l[M],Ind[N],dis[N];
     15 int disx1[N],disx2[N],disy1[N],disy2[N],used[N];
     16 queue<int>q;
     17 
     18 void add(int u,int v,int l)
     19 {
     20     edge[++num_edge].to=v;
     21     edge[num_edge].next=head[u];
     22     edge[num_edge].len=l;
     23     head[u]=num_edge;
     24 }
     25 
     26 void Spfa(int s,int *dis)
     27 {
     28     dis[s]=0;
     29     used[s]=true;
     30     q.push(s);
     31     while (!q.empty())
     32     {
     33         int x=q.front();
     34         q.pop();
     35         for (int i=head[x]; i; i=edge[i].next)
     36             if (dis[x]+edge[i].len<dis[edge[i].to])
     37             {
     38                 dis[edge[i].to]=dis[x]+edge[i].len;
     39                 if (!used[edge[i].to])
     40                 {
     41                     used[edge[i].to]=true;
     42                     q.push(edge[i].to);
     43                 }
     44             }
     45         used[x]=false;
     46     }
     47 }
     48 
     49 void Toposort()
     50 {
     51     for (int i=1; i<=n; ++i)
     52         if (!Ind[i]) q.push(i);
     53     while (!q.empty())
     54     {
     55         int x=q.front();
     56         q.pop();
     57         for (int i=head[x]; i; i=edge[i].next)
     58         {
     59             Ind[edge[i].to]--;
     60             dis[edge[i].to]=max(dis[edge[i].to],dis[x]+edge[i].len);
     61             ans=max(ans,dis[edge[i].to]);
     62             if (!Ind[edge[i].to])
     63                 q.push(edge[i].to);
     64         }
     65     }
     66 }
     67 
     68 int main()
     69 {
     70     scanf("%d%d",&n,&m);
     71     scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
     72     for (int i=1; i<=m; ++i)
     73     {
     74         scanf("%d%d%d",&u[i],&v[i],&l[i]);
     75         add(u[i],v[i],l[i]);
     76         add(v[i],u[i],l[i]);
     77     }
     78     memset(disx1,0x7f,sizeof(disx1));
     79     memset(disy1,0x7f,sizeof(disy1));
     80     memset(disx2,0x7f,sizeof(disx2));
     81     memset(disy2,0x7f,sizeof(disy2));
     82     Spfa(x1,disx1);
     83     Spfa(x2,disx2);
     84     Spfa(y1,disy1);
     85     Spfa(y2,disy2);
     86 
     87     memset(edge,0,sizeof(edge));
     88     memset(head,0,sizeof(head));
     89     num_edge=0;
     90 
     91     for (int i=1; i<=m; ++i)
     92     {
     93         int len1=min(disx1[u[i]],disx1[v[i]]) + l[i] + min(disy1[u[i]],disy1[v[i]]);
     94         int len2=min(disx2[u[i]],disx2[v[i]]) + l[i] + min(disy2[u[i]],disy2[v[i]]);
     95         if (len1!=disx1[y1] || len2!=disx2[y2]) continue;
     96         if (disx1[u[i]]<disx1[v[i]]) add(u[i],v[i],l[i]),Ind[v[i]]++;
     97         else  add(v[i],u[i],l[i]),Ind[u[i]]++;
     98     }
     99     Toposort();
    100     printf("%d",ans);
    101 }
  • 相关阅读:
    hutool工具之验证码登录
    jsp下拉框
    MyBatis错误之找不到实体类
    MybatisDay1
    JDBCUtil
    JDBC-1
    SQL学习笔记day01
    CoreJava基础面试题
    每日leetcode-数组-54. 螺旋矩阵
    每日leetcode-数组-396. 旋转函数
  • 原文地址:https://www.cnblogs.com/refun/p/8685620.html
Copyright © 2011-2022 走看看