【codeforces 954 D】 fight against traffic (最短路)

文章目錄

題意

一張無向連通圖。

現在要求再加一條無向邊,保證加邊之後無重邊自環,且 sstt 的最短路長度不變。

問有多少種加邊方案。

思路

簡單圖論題,但是我胡了一個假的做法並且在長達一天的時間裏一直以爲自己是對的 qwq

做法是先分別求出所有點 sstt 的最短路。

然後枚舉兩個原圖中沒有連邊的點 i,ji,j,判斷連上之後 (s,i,j,t)(s,i,j,t) 或者 (s,j,i,t)(s,j,i,t) 這兩條路能否更新最短路,不能就計入答案。

然後來講一下錯誤思路:對於 ss 求出所有點到他的距離。枚舉 sstt 的最短路上的點 iidis[j]dis[i]2dis[j]\le dis[i]-2 的點 jj 顯然不能連,去掉。

但很顯然這是錯的,連接兩個不在原圖 sstt 最短路上的點是有可能更新最短路的。這個隨便畫個圖就可以說明了。

代碼

// cf 954 D
#include<bits/stdc++.h>
using namespace std;
const int N = 1000 + 10, M = 2000 + 10;
int n, m, s, t;
int h[N], ecnt, nxt[M], v[M];
bool mp[N][N];
int dis[2][N], ans;

void _add(int x, int y){
	nxt[++ecnt] = h[x]; v[ecnt] = y;
	h[x] = ecnt; mp[x][y] = 1;
}

queue<int> que;
void dijkstra(int s, int *dis){
	for (int i = 1; i <= n; ++ i) dis[i] = -1;
	que.push(s); dis[s] = 0;
	while (!que.empty()){
		int u = que.front(); que.pop();
		for (int i = h[u]; i; i = nxt[i])
			if (dis[v[i]] == -1){
				dis[v[i]] = dis[u]+1;
				que.push(v[i]);
			}
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin >> n >> m >> s >> t;
	ecnt = 1;
	for (int i = 1; i <= m; ++ i){
		int x, y;
		cin >> x >> y;
		_add(x, y); _add(y, x);
	}
	dijkstra(s, dis[0]);
	dijkstra(t, dis[1]);
	for (int i = 1; i <= n; ++ i)
		for (int j = i+1; j <= n; ++ j)
			if (!mp[i][j]){
				ans += min(dis[0][i]+dis[1][j]+1, dis[1][i]+dis[0][j]+1) >= dis[0][t];
			}
	cout << ans << endl;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章