洛谷P2149 Elaxia的路线

本文介绍了一种解决两对点最短路径问题的方法,通过四次SPFA算法结合拓扑排序,找到两个最短路径间的最长公共路径。文章详细解释了算法思路,包括如何确定边是否属于最短路径,以及如何重建图并求解最长路径。

传送门啦

分析:

我最开始想的是跑两遍最短路,然后记录一下最短路走了哪些边(如果有两条最短路就选经过边多的),打上标记。两边之后找两次都标记的边有多少就行了。

但。。。我并没有实现出来。

最后让我们看一下正解:

四边spfa+拓扑排序求最长边

先让我们考虑如何求两对点最短路的最长公共路径?

1.先明白:如果有一条边,它的起点到最短路的起点 + 终点到最短路的终点 + 边权 == 最短路起点到终点的距离,那么这条边一定在最短路上。

也就是说如果有一条边i:from -> to权值是w在最短路x -> y上,那么有disx->from + disto->y + edge[i].w == disx->y

2.所以就可以把两条最短路径都经过的边重新建图

3.最后就是求最长路即可(显然图是DAG 拓扑排序可以求)。

注意!!注意!!注意!!

1.最开始我们建的是无向图,也就是说:dis_{from->to} + wdisfrom>to+w 和 dis_{to->from} + wdisto>from+w是一样的。

2.重新建图的时候我们建的是有向图。

最短路和普通的spfaspfa没什么区别,稍微改了一下dis数组,那样就不用开4个dis了。

拓扑序也差不多,ind[i]ind[i]表示第ii点的入度。

总体来说,这个题主要还是想法,还有对基础算法的应用。挺好一个题。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 1505;

inline int read(){
    char ch = getchar(); int f = 1 , x = 0;
    while(ch > '9' || ch < '0'){if(ch == '-') f = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = (x << 3) + (x << 1) + ch - '0'; ch = getchar();}
    return x * f;
}

int n,m,x,y,xx,yy,u,v,w;
struct Edge{
    int from,to,next,val;
    int tag;
}edge[maxn * maxn] , e[maxn * maxn];
int head1[maxn],tot1,head2[maxn],tot2;
int dis[5][maxn],ind[maxn];
bool vis[maxn];
int f[maxn];

void add(int u,int v,int w){
    edge[++tot1].to = v;
    edge[tot1].from = u;
    edge[tot1].next = head1[u];
    edge[tot1].val = w;
    head1[u] = tot1;
}

void addedge(int u,int v,int w){
    e[++tot2].from = u;
    e[tot2].to =     v;
    e[tot2].val = w;
    e[tot2].next = head2[u];
    head2[u] = tot2;
}

void spfa(int s,int flag){
    queue<int> q;
    for(int i=1;i<=n;i++)  dis[flag][i] = 1e9;
    memset(vis,false,sizeof(vis));
    q.push(s);
    dis[flag][s] = 0;  vis[s] = true;
    while(!q.empty()){
        int cur = q.front();
        q.pop(); vis[cur] = false;
        for(int i=head1[cur];i;i=edge[i].next){
            int v = edge[i].to;
            if(dis[flag][v] > dis[flag][cur] + edge[i].val){
                dis[flag][v] = dis[flag][cur] + edge[i].val;
                if(vis[v] == 0){
                    q.push(v);
                    vis[v] = true;
                }
            }
        }
    }
}

inline void topo(){
    queue<int> que;
    que.push(x);
    while(!que.empty()){
        int cur = que.front();
        que.pop();
        for(int i=head2[cur];i;i=e[i].next){
            int v = e[i].to , w = e[i].val;
            --ind[v];
            if(!ind[v]) {
                que.push(v);
                f[v] = max(f[v] , f[cur] + e[i].tag * w);
            }
        }
    }
}

void rebuild(){
    for(int i=1;i<=tot1;i++){
        int v = edge[i].to , u = edge[i].from , w = edge[i].val;
        if(dis[1][u] + w + dis[2][v] == dis[1][y]){
            addedge(u , v , w);
            if(dis[3][u] + w + dis[4][v] == dis[3][yy] || dis[3][v] + w + dis[4][u] == dis[3][yy])
            //为了处理无向图的问题 
            e[tot2].tag = 1;
            ind[v]++;
        }
    }
}

int main(){
    n = read(); m = read();
    x = read(); y = read(); xx = read(); yy = read();
    for(int i=1;i<=m;i++){
        u = read(); v = read(); w = read();
        add(u , v , w);
        add(v , u , w);
    }
    spfa(x , 1);
    spfa(y , 2);
    spfa(xx , 3);
    spfa(yy , 4);
    rebuild();
    topo();
    printf("%d\n",f[y]);
    return 0;
}

 

转载于:https://www.cnblogs.com/Stephen-F/p/9864749.html

## 01、数据介绍 数据整理全国30个省份制造业细分行业产值,能够反映一定时期内细分行业工业生产总规模和总水平的指标,是计算工业生产发展速度和主要比例关系、计算工业产品销售率等其他经济指标的基础。先进制造业数据可用于两业融合测算。 数据名称:全国30省-制造业细分行业产值/先进制造业细分行业产值数据 数据年份:2001-2022年 ## 02、数据指标 农副食品加工业;食品制造业;饮料制造业;烟草制造业;纺织业;纺织服装鞋帽制造业;皮革、毛皮、羽毛(绒)极其制品业;木材加工及木、竹、藤、棕、草制品业;家具制造业;造纸及纸制品业;印刷业和记录媒介的复制;文教体育用品制造业;石油加工、炼焦及核燃料加工业化;学原料及化学制品制造业;医药制造业;化学纤维制造业;橡胶和塑料制品制品业;非金属矿物制品业;黑色金属冶炼及压延加工业;有色金属冶炼及压延加工业;金属制品业;通用设备制造业;专用设备制造业;汽车制造业;其他运输设备制造业;电气机械及器材制造业;通信设备计算机及其他电子设备制造业;仪器仪表及文化、办公用机械制造业;其他制造业;废弃资源和废旧材料回收加工业;制造业总产值 印刷业和记录媒介的复制;石油加工、炼焦及核燃料加工业;化学原料及化学制品制造业;医药制造业;橡胶和塑料制品制品业;非金属矿物制品业;黑色金属冶炼及压延加工业;有色金属冶炼及压延加工业;金属制品业;通用设备制造业;专用设备制造业;汽车制造业;其他运输设备制造业;电气机械及器材制造业;通信设备计算机及其他电子设备制造业;仪器仪表及文化、办公用机械制造业;废弃资源和废旧材料回收加工业
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值