最大值(最短路+最短路计数)
洛谷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
*/

浙公网安备 33010602011771号