最大值(最短路+最短路計數)

cn是大帅哥886發表於2024-07-13

洛谷CF449B


第1題 最大值 檢視測評資料資訊

給定一個包含n個點和m條邊的無向圖,以及k條特殊的直接連線節點1的邊。每條邊都有一個權重,表示兩點之間的距離。現在,我們想知道最多可以移除這k條特殊邊中的多少條,而保持圖中每個節點到節點1的最短距離不變。

輸入格式

第一行n,m,k

接下來m行,每行三個整數x,y,z(x!=y),表示x到y之間有一條邊權為z的無向邊。

接下來k行,每行兩個整數xx和yy,表示節點1到點xx有一條邊權為yy的邊。

1<=x,y,xx<=n<=1e5,1<=k<=1e5,1<=m<=3e5,1<=z,yy<=1e9

輸出格式

一個整數,表示最多刪除的邊數。

輸入/輸出例子1

輸入:

5 5 3

1 2 1

2 3 2

1 3 3

3 4 4

1 5 5

3 5

4 5

5 5

輸出:

2

樣例解釋

這題考慮分類討論。

1.加入的邊比最短路大,那就刪掉也沒事

2.加入的邊等於最短路,那得看有幾條這種邊,留到至少還剩一條才行(此處可用最短路計數)

3.加入的邊比最短路小,不可能的情況。捨去

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;

int n, m, k, u1, v1, v2[N], w2[N], w1, dis[N], vis[N], cnt[N], ans=0;
struct node
{
	int u, w;
	bool operator <(const node &A) const
	{
		return w>A.w;
	};
};
vector<node> a[N];
priority_queue<node> q;
void dij()
{
	memset(dis, 63, sizeof dis);
	memset(vis, 0, sizeof vis);
	
	dis[1]=0;
	q.push({1, 0});
	
	while (!q.empty())
	{
		int u=q.top().u;
		q.pop();
		
		if (vis[u]) continue;
		vis[u]=1;
		
		for (int i=0; i<a[u].size(); i++)
		{
			int v=a[u][i].u, w=a[u][i].w;
			if (dis[v]==dis[u]+w) cnt[v]++;
			if (dis[v]>dis[u]+w)
			{
				dis[v]=dis[u]+w;
				cnt[v]=1;
				q.push({v, dis[v]});
			}
		}
	}
}
int main()
{
	scanf("%d%d%d", &n, &m, &k);
	for (int i=1; i<=m; i++)
	{
		scanf("%d%d%d", &u1, &v1, &w1);
		a[u1].push_back({v1, w1});
		a[v1].push_back({u1, w1});
	}
	for (int i=1; i<=k; i++)
	{
		scanf("%d%d", &v2[i], &w2[i]);
		a[1].push_back({v2[i], w2[i]});
		a[v2[i]].push_back({1, w2[i]});
	}
	dij();
//	for (int i=1; i<=n; i++) cout<<cnt[i]<<endl;
	
	for (int i=1; i<=k; i++)
	{
		if (w2[i]>dis[v2[i]]) ans++;
		if (w2[i]==dis[v2[i]] && cnt[v2[i]]>1) ans++, cnt[v2[i]]--;
	}
	printf("%d", ans);
	return 0;
}
/*
5 4 1
1 2 4
2 3 1
3 5 1
4 5 1
3 2


5 5 3
1 2 1
2 3 2
1 3 3
3 4 4
1 5 5
2 1
2 1
2 1
*/ 

  

相關文章