为缓解 S 城与日俱增的交通压力,S 城的市长准备修一条路
S 城共有 n 个街区,它们由 m 条双向道路相连,每条道路的长度相等
作为 S 城的天才,小 X 了解到 S 城的交通压力主要来自于最繁华的 S 街区和 T 街区
如果新修的路不能使 S 街区到 T 街区的距离缩短,就不能缓解 S 城的交通压力
S 城的市长自然不了解这一点。现在小 X 想知道,有多少种修路方案不能缓解 S 城的交通压力
注意,对于修路方案 (u,v) 和 (v,u) 视为同一种方案,新修的路不能在原图中存在

又是一道送分题,\(\Theta{(n)}\) 预处理出所有点距离两个繁华街区的距离

\(\Theta{(n^2)}\) 暴力查询每条路径是否会让路径变短

本来想的优化是:如果两个点都不在两繁华街区之间,说明这条路对路径不会有任何影响,直接continue

结果发现查询每条路本来就是 \(\Theta{(1)}\) 的,所以这优化并没有什么用……

代码

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

int n,m,s,t,u,v;

struct Edge
{
    int next,to;
}edge[4005];
int cnt=0,head[4005];

int diss[2005],dist[2005];
bool viss[2005],vist[2005];

inline void add_edge(int from,int to)
{
    edge[++cnt].next=head[from];
    edge[cnt].to=to;
    head[from]=cnt;
}

template<class T>inline void read(T &res)
{
    char c;T flag=1;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}

inline void init()
{
    for(register int i=1;i<=n;++i) diss[i]=dist[i]=inf;
    diss[s]=0;dist[t]=0;
}

queue<int> q;

int exsts[2005],nos[2005];
void bfss(int u)
{
    q.push(u);
    while(!q.empty())
    {
        int u=q.front();q.pop();nos[u]=0;
        for(register int i=head[u];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(diss[v]>diss[u]+1)
            {
                diss[v]=diss[u]+1;
                if(!nos[v])
                {
                    nos[v]=1;
                    q.push(v);
                }
            }
        }
    }
}

int exstt[2005],nott[2005];
void bfst(int u)
{
    q.push(u);
    while(!q.empty())
    {
        int u=q.front();q.pop();nott[u]=0;
        for(register int i=head[u];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dist[v]>dist[u]+1)
            {
                dist[v]=dist[u]+1;
                if(!nott[v])
                {
                    nott[v]=1;
                    q.push(v);
                }
            }
        }
    }
}

bool hav[1005][1005];
bool usef[2005];//有用的点
int main()
{
    freopen("road.in","r",stdin);
    freopen("road.out","w",stdout);
    read(n);read(m);read(s);read(t);
    init();
    for(register int i=1;i<=m;++i)
    {
        read(u);read(v);
        add_edge(u,v);
        add_edge(v,u);
        hav[u][v]=hav[v][u]=1;
    }
    bfss(s); bfst(t);
    int predis=diss[t];
    int ans=0;
    for(register int i=1;i<=n;++i) if(diss[i]>predis&&dist[i]>predis) usef[i]=1;
//  cout<<"!"<<endl;
//  cout<<predis<<endl;
//  cout<<diss[1]<<" "<<dist[3]<<" "<<dist[1]<<" "<<diss[3]<<endl;
    for(register int i=1;i<n;++i)//枚举每一种修路方法
    {
        for(register int j=i+1;j<=n;++j)
        {
            if(i==j||hav[i][j]) continue;
            if(usef[i]&&usef[j])
            {
                ans++;
//              cout<<"useless: "<<i<<" "<<j<<endl;
                continue;
            }
            else if(diss[i]+1+dist[j]<predis) continue;
            else if(dist[i]+1+diss[j]<predis) continue;
//          cout<<i<<" "<<j<<endl;
            ans++;
        }
    }
    printf("%d\n",ans);
    return 0;
}
02-13 21:53