题目:http://codeforces.com/contest/954/problem/D
题意:
起点s,终点t,求有多少种加边方案,使得两点最短路不变短;
已经有边直接相连的点不能再加边。
分析:
s、t为起点两遍spfa;
O(n^2)枚举加边,不变短ans++。
代码:
#include <bits/stdc++.h>
using namespace std;
const int tmax=1005,inf=2147483647;
int n,m,s,t,d1[tmax],d2[tmax],ans;
vector<int> G[tmax];
queue<int> Q;
bool in[tmax],E[tmax][tmax];
void spfa(int x,int *d)
{
int i,tmp,len,to;
for(i=1;i<=n;i++)
d[i]=inf;
memset(in,0,sizeof(in));
while(!Q.empty()) Q.pop();
Q.push(x);
in[x]=true;
d[x]=0;
while(!Q.empty())
{
tmp=Q.front();
Q.pop();
in[tmp]=false;
len=G[tmp].size();
for(i=0;i<len;i++)
{
to=G[tmp][i];
if(d[to]>d[tmp]+1)
{
d[to]=d[tmp]+1;
if(in[to]==false)
{
Q.push(to);
in[to]=true;
}
}
}
}
return;
}
int main()
{
cin>>n>>m>>s>>t;
int i,j,x,y;
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
E[x][y]=E[y][x]=true;
}
spfa(s,d1);
spfa(t,d2);
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
if(E[i][j]==true) continue;
if(d1[i]<inf&&d2[j]<inf&&d1[t]>d1[i]+1+d2[j]) continue;
if(d1[j]<inf&&d2[i]<inf&&d1[t]>d1[j]+1+d2[i]) continue;
ans++;
}
}
cout<<ans;
return 0;
}