题目链接:https://codeforc.es/contest/954/problem/D
题意:
起点s,终点t,求有多少种加边方案,使得两点最短路不变短;
已经有边直接相连的点不能再加边。
解法:从s出发跑一遍最短路,从t出发跑一遍最短路,然后枚举连边,如果最短路比这条新路短,那么合法ans++
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
const int N=1e3+10,inf=0x3f3f3f3f;
int ma[N][N],n,m,s,t;
int dis[N],d,d2[N];
struct node{
int id,w;
bool operator <(const node &a)const{
return a.w<w;
}
};
void bfs(int s)
{
for(int i=1;i<=n;++i) dis[i]=inf;
priority_queue<node>que;
que.push({s,0});
dis[s]=0;
while(que.size()){
node u=que.top();que.pop();
for(int i=1;i<=n;++i){
if(ma[u.id][i]){
if(dis[i]>u.w+1){
dis[i]=u.w+1;
que.push({i,dis[i]});
}
}
}
}
}
void bfs_1(int s)
{
for(int i=1;i<=n;++i) d2[i]=inf;
priority_queue<node>que;
que.push({s,0});
d2[s]=0;
while(que.size()){
node u=que.top();que.pop();
for(int i=1;i<=n;++i){
if(ma[u.id][i]){
if(d2[i]>u.w+1){
d2[i]=u.w+1;
que.push({i,d2[i]});
}
}
}
}
}
int main()
{
cin>>n>>m>>s>>t;
for(int i=1;i<=m;++i){
int u,v;
cin>>u>>v;
ma[u][v]=ma[v][u]=1;
}
bfs(s);
bfs_1(t);
//printf("d:%d\n",d);
int ans=0;
for(int i=1;i<n;++i){
for(int j=i+1;j<=n;++j){
if(ma[i][j]==0){
if(dis[t]<=dis[i]+1+d2[j]&&dis[t]<=dis[j]+1+d2[i]) ans++;
}
}
}
printf("%d\n",ans);
}