Educational Codeforces Round 40 D. Fight Against Traffic

37 篇文章 0 订阅
12 篇文章 0 订阅

题意大致就是给定一幅无向图,起点,终点,然后问在那些没有用一条路不经过其他点直接连通的点之间连新的路,并且新的路不应该改变起点到终点的最短距离,问这样的路有多少条;
朴素25%的算法,就是枚举所有的点对,然后如果两个点之间没有直接的路,就加一条然后跑最短路,与原距离比较。从第8个点开始就会tle….
比较机智的算法就是,以s,t分别为起点跑一次最短路,然后枚举所有没有直接相连的两个点a,b,如果起点s到a的距离加上终点t到b的距离再加上a到b的距离(1),以及如果起点s到b的距离加上终点t到a的距离再加上a到b的距离(1),比原来的dis[t]大或者等于的话,就可以加上这条路。
这相当于是在算加上ab这条边后的最短路有没有可能变短。
具体细节见代码;

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
struct edge{
    int to,cost;
};
vector<edge>G[1005];
bool connect[1005][1005];
int dis[1005];bool inque[1005];
void spfa(int x)
{
    memset(dis,0x3f,sizeof(dis));dis[x]=0;
    queue<int>que;que.push(x);
    while(!que.empty()){
        int t=que.front();que.pop();inque[t]=false;
        for(int i=0;i<G[t].size();i++){
            edge e=G[t][i];
            if(dis[e.to]>dis[t]+e.cost){
                dis[e.to]=dis[t]+e.cost;
                if(!inque[e.to]){
                    que.push(e.to);inque[e.to]=true;
                }
            }
        }
    }
}
int main()
{
    int n,m,s,t,i,j,k;
    cin>>n>>m>>s>>t;
    for(i=1;i<=m;i++){
        int a,b;scanf("%d%d",&a,&b);
        G[a].push_back(edge{b,1});G[b].push_back(edge{a,1});
        connect[a][b]=connect[b][a]=true;
    }
    spfa(s);int dis1[1005];for(i=1;i<=n;i++)dis1[i]=dis[i];//用一个新的数组记录第一次spfa的数据
    spfa(t);int cnt=0;
    for(i=1;i<=n;i++){
        for(j=i+1;j<=n;j++){
            if(connect[i][j])continue;//本来就联通,直接跳过
            if(dis1[i]+dis[j]+1>=dis1[t]&&dis1[j]+dis[i]+1>=dis1[t])//如果加上边之后的最短路依然大于等于原最短路的话
                cnt++;
        }
    }
    cout<<cnt<<endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值