洛谷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 */