Codeforces 1076D——最短路算法
2024-08-24 12:53:11
题目
给你一个有n个顶点、m条边的无向带权图。需要擦除一些边使得剩余的边数不超过k,如果一个点在原始图到顶点1的最短距离为d,在删边后的图中到顶点的最短距离仍是d,则称这种点是 good。问如何删边,使得 good点最多。
分析
首先调用最短路算法求各点到顶点1的最短距离,同时记录下每点在最短路上的前一个顶点。然后从顶点1出发搜索一个大小为k的联通块即可(如果够k个)
代码
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std; typedef long long ll; const ll INF = (ll) << ;
const int maxv = + ; //最大顶点数
const int maxe = * + ; //最大边数
ll dis[maxv]; //源到各顶点的最短距离
int vis[maxv]; //记录是否被收录,用来代替集合S
int head[maxv]; //采用链式前向星建图
int pre[maxv]; //最短路树,记录前一个节点 vector<int>ans; //记录答案
int n, m, k; //顶点数、边数、最大保留的边数 struct Node
{
int u;
ll d; //该节点的编号与距离
bool operator < (const Node x) const
{
return d > x.d;
}
}; struct Edge
{
int to, w, next;
}edge[maxe]; inline void addedge(int u, int v, int w, int id)
{
edge[id].to = v;
edge[id].w = w;
edge[id].next = head[u];
head[u] = id;
}
//s为起点
void Dijsktra(int s)
{
priority_queue<Node>q; //取出集合T中的最小值
memset(vis, , sizeof(vis));
memset(pre, -, sizeof(pre));
//memset(dis, INF, sizeof(dis)); //与邻接矩阵不同,这里初始化为INF就可以,原因自己想
for (int i = ; i <= n; i++) dis[i] = INF; dis[s] = ;
q.push(Node{ s, dis[s] });
while (!q.empty())
{
Node x = q.top(); q.pop();
int u = x.u; if (vis[u]) continue; vis[u] = true;
for (int i = head[u]; i != -; i = edge[i].next) //松弛与u直接相邻的顶点
{
int v = edge[i].to;
int w = edge[i].w;
if (!vis[v] && dis[u] + w < dis[v])
{
dis[v] = dis[u] + w;
pre[v] = u; //记录最短路树的父节点
q.push(Node{ v,dis[v] });
}
}
}
} //从s出发找出最短路树上的k个节点(不到k个就是全部节点)
void bfs(int s)
{
queue<int>q;
q.push(s);
while (!q.empty())
{
int u = q.front(); q.pop();
for (int e = head[u]; e != -; e = edge[e].next)
{
int v = edge[e].to;
if (pre[v] == u && ans.size() < k)
{
q.push(edge[e].to);
ans.push_back(e / + ); //无向边建图时存了两遍,真实序号位e/2+1
}
}
if (ans.size() >= k) break;
}
} int main()
{
while (scanf("%d%d%d",&n,&m,&k) == )
{
memset(head, -, sizeof(head));
int id = ;
for (int i = ; i < m; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
addedge(u, v, w,id++); addedge(v, u, w,id++);
} Dijsktra(); ans.clear();
bfs();
int cnt = ans.size();
printf("%d\n", cnt);
for (int i = ; i < cnt; i++)
printf("%d%c", ans[i], i == cnt - ? '\n' : ' ');
}
return ;
}
参考链接:https://blog.csdn.net/SparkFucker/article/details/84024243
最新文章
- NOIP2016题解
- linux swap 分区那点事儿
- 分享:录制gif小图片工具
- OSSFS将OSS bucket 挂载到本地文件系统及注意事项
- Mac SVN 命令行
- LightOj 1213 - Fantasy of a Summation(推公式 快速幂)
- centOS 6 python MySQLdb 提示 no module
- 开源库CImg 数据格式存储
- 每天一个linux命令(52)--wc命令
- 关于vector push_back()与其他方式读取数据的效率对比
- Linux下批量管理工具PSSH
- java组播MulticastSocket
- 【莫比乌斯反演】BZOJ2005 [NOI2010]能量采集
- SQLServer之ISO游标使用
- 自己搭建git服务器
- Android设备一对多录屏直播--(UDP组播连接,Tcp传输)
- Ubuntu18.4中Apache在加不同端口的虚拟主机
- <;基础>; PHP 数据类型
- Router types
- Notepad++常用插件