ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF954D Fight Against Traffic 题解

2022-01-26 18:06:06  阅读:176  来源: 互联网

标签:p2 p1 题解 短路 Fight a1 枚举 a2 Traffic


题目大意

对于一个无向无权联通图 \(G\),有 \(n\) 个点 \(m\) 条边,往这个图里没有被连接的两个点之间连边,问有多少连法可以使得 \(s\) 到 \(t\) 的最短路长度不变。

解决思路

2.1 暴力做法

可以枚举任意两个点,对于每次连接使用 bfs 求最短路,计算出时间复杂度为 \(O(n^2(n+m))\),不可通过。

2.2 预处理

如果连接 \(x,y\) 两个点,我们可以通过先从 \(s\) 走到 \(x\) 或 \(y\) 点,再从另一端前往 \(t\) 点,计算出这样走的路线长度。如果这样走的路线长度大于等于两者间的最短路长度(也就是不会使最短路长度变化),那么就将计数器加一。

那我们可以预处理出 \(s\) 点到任何一个点的最短路,用 \(p1_i\) 表示。

再预处理出任意一点到 \(t\) 点的最短路,由于这是无向图,等同于求出 \(t\) 点到任意一点的最短路,用 \(p2_i\) 表示。

最后枚举两个点 \(x,y\),计算 \(p1_x+p2_y\) 和 \(p1_y+p2_x\),再和 \(p1_t\) 或者 \(p2_s\) 比较(这两者是等价的,下文中都使用 \(p1_t\))。如果 \(p1_t \leqslant p1_x+p2_y+1 \ \land \ p1_t \leqslant p1_y+p2_x+1\) 就让计数器变量加一。

代码实现

3.1 建图

采用邻接表建无向图:

for(int i=1;i<=m;i++){
	int a1,a2;
	cin>>a1>>a2;
	l[a1].push_back(a2);
	l[a2].push_back(a1);//无向图建图
    bol[a1][a2]=1;
	bol[a2][a1]=1;//表示a1和a2间有了一条边
}

这里的 \(l\) 是邻接表。

3.2 bfs 预处理最短路

q1.push(s);
p1[s]=0;
ok1[s]=1; //状态初始化,起点为s
while(!q1.empty()){
	int x=q1.front();
	q1.pop();
	for(int i=0;i<l[x].size();i++){
		if(!ok1[l[x][i]]){ //排除了反复走一个点的情况
			if(p1[l[x][i]]!=0){ //如果这个点的最短路值不是0
				p1[l[x][i]]=min(p1[l[x][i]],p1[x]+1);//比较已知的最短路和现在这条路
			}
			else{
				p1[l[x][i]]=p1[x]+1;//如果这个点还没有最短路值,就将现在这条路的长度赋值给它
			}
			q1.push(l[x][i]);//push新的状态
			ok1[l[x][i]]=1;//这个点已经走过了
		}
	}
}

用一个队列 \(q1\) 存储 bfs 的状态,用 \(\texttt{bool}\) 数组 \(ok\) 存储这个点是否走过以避免出现环的情况,用 \(p1\) 数组存储最短路的长度。

从 \(t\) 点开始的 bfs 预处理如法炮制,基本没有区别。

3.3 枚举每一个 \(x,y\)

现在我们得到了从 \(s\) 点到任意一点的最短路数组 \(p1\),从 \(t\) 点到任意一点的最短路数组 \(p2\)。

先用二重循环枚举 \(x,y\),为避免重复计算,\(y\) 的枚举从 \(x+1\) 开始,并排除掉已有边的情况。

在枚举中比较 \(p1_t\) 与 \(p1_x+p2_y+1\) 和 \(p1_y+p2_x+1\) 的值。

for(int i=1;i<=n;i++){
	for(int j=i+1;j<=n;j++){
		if(bol[i][j]){//排除掉有边的情况,这就是建图时多存储一个bool数组的作用
			continue;
		}
		if((p1[i]+p2[j])+1>=p1[t]&&(p2[i]+p1[j])+1>=p1[t]){//比较
			cnt++;//如果这条新路的长度比原最短路长,计数器加一
		}
	}
}

洛谷 AC记录

CF AC记录

标签:p2,p1,题解,短路,Fight,a1,枚举,a2,Traffic
来源: https://www.cnblogs.com/lemonniforever/p/solution-cf954d.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有