BZOJ-1880 Elaxia的路线 SPFA+枚举

34 篇文章 0 订阅

1880: [Sdoi2009]Elaxia的路线
Time Limit: 4 Sec Memory Limit: 64 MB
Submit: 921 Solved: 354
[Submit][Status][Discuss]

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,输入数据保证没有重边和自环。

Source
Day2

竟然自己rush出了正解,开心

题解:
4遍spfa,开四个dis数组,分别记录st1,st2,ed1,ed2到各点的最短路,然后枚举点对(i,j)判断i,j是否在最短路径上,然后更新答案即可.

PS:网上的好像都是DP啊,拓扑啊什么的.....

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define maxn 1510
#define maxm 500010
int n,m,ans;
int st1,st2,ed1,ed2;
int len1,len2;
struct data{int to,next,tim;}edge[maxm*2];
int head[maxn],cnt;

void add(int u,int v,int t)
{
    cnt++;
    edge[cnt].next=head[u]; head[u]=cnt;
    edge[cnt].to=v; edge[cnt].tim=t;
}
void insert(int u,int v,int t)
{
    add(u,v,t); add(v,u,t);
}

int disst1[maxn],disst2[maxn],dised1[maxn],dised2[maxn];
bool visit[maxn];
#define inf 0x7fffffff
void spfa(int s,int* dis)
{
    queue<int>q;
    for (int i=1; i<=n; i++) dis[i]=inf;
    q.push(s); dis[s]=0;
    while (!q.empty())
        {
            int now=q.front(); q.pop();
            for (int i=head[now]; i; i=edge[i].next)
                if (dis[now]+edge[i].tim<dis[edge[i].to])
                    {
                        dis[edge[i].to]=edge[i].tim+dis[now];
                        if (!visit[edge[i].to])
                            {
                                q.push(edge[i].to);
                                visit[edge[i].to]=1;
                            }
                    }
            visit[now]=0;
        }
}

bool check(int loc)
{
    if (disst1[loc]+dised1[loc]!=len1 || disst2[loc]+dised2[loc]!=len2) 
        return false;
    return true;
}

int main()
{
    n=read(),m=read();
    st1=read(),ed1=read(),st2=read(),ed2=read();
    for (int i=1; i<=m; i++)
        {
            int u=read(),v=read(),t=read();
            insert(u,v,t);
        }
    spfa(st1,disst1); spfa(st2,disst2);
    spfa(ed1,dised1); spfa(ed2,dised2);
    len1=disst1[ed1]; len2=disst2[ed2];
    for (int i=1; i<=n; i++)
        if (check(i))
            for (int j=1; j<=n; j++)
                if (check(j))
                    ans=max(ans,abs(disst1[i]-disst1[j]));
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值