codeforce 543 B 最短路

本文介绍了一种使用 SPFA 算法预处理所有最短路径的方法,并通过暴力枚举所有区间来检查是否满足特定条件,进一步优化路径。适用于解决包含两个路径约束的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


预处理所有最短路。

然后暴力所有区间,check是否满足条件然后进行松弛操作

#include <bits/stdc++.h>
using namespace std ;

typedef long long ll ;
const int inf = 0x3f3f3f3f ;
const int maxn = 3050 ;
struct edge{
    int u , v ;
    int w ;
};
vector<int> g[maxn] ;
vector<edge> Edge ;
int inq[maxn] ;
int dis[maxn][maxn] ;
int n ;
set< pair<int , int> > save ;
void addEdge(int u , int v , int w){
    edge temp ;
    temp.u = u , temp.v = v , temp.w = w ;
    Edge.push_back(temp) ;
    g[u].push_back(Edge.size() - 1 ) ;
}
bool spfa(int u)
{
    int i , k ;
    for(i = 0 ; i <= n ; i ++ ){
        dis[u][i] = inf ;
    }memset(inq , 0 , sizeof(inq)) ;
    dis[u][u] = 0 , inq[u] = 1 ;
    queue<int> q ;
    q.push(u) ;
    while(! q.empty()) {
        int t = q.front() ; q.pop() ;
        inq[t] = 0 ;
        for(k = 0 ; k < g[t].size() ; k ++ ){
            edge e = Edge[ g[t][k] ] ;
            if(dis[u][e.v] > dis[u][e.u] + e.w){
                dis[u][e.v]= dis[u][e.u] + e.w ;
                //pre[e.v] = e.u ;
                if(! inq[e.v]){
                    inq[e.v] = 1 ;
                    q.push(e.v) ;
                }
            }
        }
    }
    return true ;
}
int work(){
    for(int i = 1 ; i <= n ; i ++ ) spfa(i) ;
    int s1 , t1 , s2 , t2 , len1 , len2 ;
    save.clear() ;
    scanf("%d %d %d" , &s1 , &t1 , &len1) ;
    scanf("%d %d %d" , &s2 , &t2 , &len2) ;

    if(dis[s1][t1] > len1 || dis[s2][t2] > len2) return -1 ;

    int ans = dis[s1][t1] + dis[s2][t2] ;
    int D1 = dis[s1][t1] , D2 = dis[s2][t2] ;
    for(int i = 1 ; i <= n ; i ++ ){
        for(int j = i + 1 ; j <= n ; j ++ ){
            if(dis[s1][i] + dis[i][j] + dis[j][t1] <= len1 && dis[s2][i] + dis[i][j] + dis[j][t2] <= len2)
                ans = min(ans , dis[s1][i] + dis[i][j] + dis[j][t1] + dis[s2][i] + dis[j][t2]) ;
            if(dis[s1][i] + dis[i][j] + dis[j][t1] <= len1 && dis[s2][j] + dis[j][i] + dis[i][t2] <= len2)
                ans = min(ans , dis[s1][i] + dis[i][j] + dis[j][t1] + dis[s2][j] + dis[i][t2]) ;
            if(dis[s1][j] + dis[j][i] + dis[i][t1] <= len1 && dis[s2][i] + dis[i][j] + dis[j][t2] <= len2)
                ans = min(ans , dis[s1][j] + dis[i][j] + dis[i][t1] + dis[s2][i] + dis[j][t2]) ;
            if(dis[s1][j] + dis[j][i] + dis[i][t1] <= len1 && dis[s2][j] + dis[j][i] + dis[i][t2] <= len2)
                ans = min(ans , dis[s1][j] + dis[i][j] + dis[i][t1] + dis[s2][j] + dis[i][t2]) ;
        }
    }

    return ans ;
}
int main(){
    int m , a , b ;
    while( ~ scanf("%d %d" , &n , &m)){
        for(int i = 0 ; i < m ; i ++ ){
            scanf("%d %d" , &a , &b) ;
            addEdge(a , b , 1 ) ;
            addEdge(b , a , 1 ) ;
        }
        int ans = work() ;
        printf("%d\n" , ans == -1 ? -1 : m - ans) ;
    }
    return 0 ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值