[20190923机房测试] 修路

为缓解 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
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/tqr06/p/11572925.html