题意大致就是给定一幅无向图,起点,终点,然后问在那些没有用一条路不经过其他点直接连通的点之间连新的路,并且新的路不应该改变起点到终点的最短距离,问这样的路有多少条;
朴素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;
}