题目

给你一个有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

最新文章

  1. NOIP2016题解
  2. linux swap 分区那点事儿
  3. 分享:录制gif小图片工具
  4. OSSFS将OSS bucket 挂载到本地文件系统及注意事项
  5. Mac SVN 命令行
  6. LightOj 1213 - Fantasy of a Summation(推公式 快速幂)
  7. centOS 6 python MySQLdb 提示 no module
  8. 开源库CImg 数据格式存储
  9. 每天一个linux命令(52)--wc命令
  10. 关于vector push_back()与其他方式读取数据的效率对比
  11. Linux下批量管理工具PSSH
  12. java组播MulticastSocket
  13. 【莫比乌斯反演】BZOJ2005 [NOI2010]能量采集
  14. SQLServer之ISO游标使用
  15. 自己搭建git服务器
  16. Android设备一对多录屏直播--(UDP组播连接,Tcp传输)
  17. Ubuntu18.4中Apache在加不同端口的虚拟主机
  18. &lt;基础&gt; PHP 数据类型
  19. Router types
  20. Notepad++常用插件

热门文章

  1. 【前端】CentOS 7 系列教程之六: 安装 mysql 5.7
  2. (二十六)分类信息的curd-分类信息添加
  3. Windows下允许redis远程访问
  4. ubuntu的NAT方式上网配置
  5. HDU6035:Colorful Tree(树形DP)
  6. vim 不同的插入方式
  7. Jenkins自动化部署——持续交付
  8. Python 基础知识(5)
  9. 跟我一起玩Win32开发(5):具有单选标记的菜单
  10. c++ 优先级大全