[SDOI2009] Elaxia的路线

题目描述:

求两个起终点的最短路的最长公共路径

题目分析:

我们跑4遍SPFA,分别求出四个点到所有点的最短路.
枚举每条边 然后判断这条边是否都满足两者的最短路
最后做一下拓扑求一下最长路径即可

题目链接:

Luogu 2149

Ac 代码:

// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
const int maxm=1e6+100;
int dis[4][maxm];
int head[maxm],to[maxm<<1],net[maxm<<1],cost[maxm<<1],cnt;
bool vis[maxm];
int du[maxm],ans[maxm];
std::queue <int> dl;
int n,m;
int s1,t1,s2,t2;
inline void addedge(int u,int v,int c)
{
    cnt++;
    to[cnt]=v,cost[cnt]=c,net[cnt]=head[u],head[u]=cnt;
}
int ahead[maxm],ato[maxm<<1],anet[maxm<<1],acost[maxm<<1],acnt;
inline void Addedge(int u,int v,int c)
{
    acnt++;
    du[v]++;
    ato[acnt]=v,acost[acnt]=c,anet[acnt]=ahead[u],ahead[u]=acnt;
}
inline void SPFA(int s,int t)
{
    dis[t][s]=0;
    vis[s]=1;
    dl.push(s); 
    while(!dl.empty())
    {
        int now=dl.front();
        dl.pop();
        vis[now]=0;
        for(int i=head[now];i;i=net[i])
        if(dis[t][to[i]]>dis[t][now]+cost[i])
        {
            dis[t][to[i]]=dis[t][now]+cost[i];
            if(!vis[to[i]]) vis[to[i]]=1,dl.push(to[i]);
        }
    }
}
struct node{
    int u,v,cost;
}d[maxm];
void topsort()
{
    int res=0;
    for(int i=1;i<=n;i++)
    if(!du[i]) dl.push(i);
    while(!dl.empty())
    {
        int now=dl.front();
        dl.pop();
        for(int i=ahead[now];i;i=anet[i])
        {
            int tmp=ato[i];
            ans[tmp]=std::max(ans[tmp],ans[now]+acost[i]);
            res=std::max(res,ans[tmp]);
            du[tmp]--;
            if(!du[tmp]) dl.push(tmp); 
        }
    }
    printf("%d\n",res);
}
int main()
{
    memset(dis,127/3,sizeof(dis));
    scanf("%d%d",&n,&m);
    scanf("%d%d%d%d",&s1,&t1,&s2,&t2);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&d[i].u,&d[i].v,&d[i].cost);
        addedge(d[i].u,d[i].v,d[i].cost);
        addedge(d[i].v,d[i].u,d[i].cost);
    }
    SPFA(s1,0),SPFA(t1,1),SPFA(s2,2),SPFA(t2,3);
    for(int i=1;i<=m;i++)
    {
        int u=d[i].u,v=d[i].v,c=d[i].cost;
        int c1=std::min(dis[0][u],dis[0][v])+std::min(dis[1][u],dis[1][v])+c;
        int c2=std::min(dis[2][u],dis[2][v])+std::min(dis[3][u],dis[3][v])+c;
        if(c1==dis[0][t1]&&c2==dis[2][t2])
         dis[0][u]<dis[0][v]?Addedge(u,v,c):Addedge(v,u,c);
    }
    topsort();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值