<题目链接>

题目大意:

n个点,m条边的无向图,现在需要删除一些边,使得剩下的边数不能超过K条。1点为起点,如果1到 i 点的最短距离与删除边之前的最短距离相同,则称 i 为 "good vertice",现在问你如果要使 "good vertice"最多,需要留下多少条边,并且输出这些边的序号。

解题分析:

我们最多只能留k条边 (或者是n-1条边,因为经过Dijkstra松弛后,其实只需要n-1条边就能使起点到所有点的最短距离仍然为未删边时的最短距离,想一下Dijkstra的松弛过程就能明白)。

那如何留下的 "good vertice" 最多呢?其实 "good vertice" 就是指我们尽量不要破坏原来的最短路径,那些越先通过Dijkstra松弛得到最短路的点的最短路径所需的维护的路径数量是最少的,所以我们贪心的将松弛的前K个点的之前的路劲记录即可,这样延伸出的连通块能够让其中所有的点到起点的最短距离等于原始的最短距离,同时他们所需维护的路径还是尽可能的少的。

 #include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std; #define M int(3e5+10)
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define pb push_back
#define clr(a,b) memset(a,b,sizeof(a))
#define INF ll(1e18)
typedef long long ll;
int cnt,head[M],loc[M];
bool vis[M];
vector<int>vec;
int n,m,k; template<typename T>
inline T read(T&x){
x=;int f=;char ch=getchar();
while (ch<'' || ch>'') f|=(ch=='-'),ch=getchar();
while (ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return x=f?-x:x;
}
struct Edge{
int to,ord,next;
ll val;
}edge[M<<]; struct Node{
int ord;ll dist;
Node(int _ord=,ll _dist=):ord(_ord),dist(_dist){}
bool operator < (const Node &tmp)const {
return dist>tmp.dist;
}
}d[M];
void init(){
cnt=;clr(head,-);
}
void addedge(int u,int v,ll w,int c){
edge[++cnt].to=v;edge[cnt].val=w,edge[cnt].ord=c;
edge[cnt].next=head[u];head[u]=cnt;
}
void Dijkstra(){
priority_queue<Node>q;
for(int i=;i<=n;i++)
d[i].dist=INF,d[i].ord=i,vis[i]=false;
d[].dist=;q.push(d[]);
while(q.size()){
int u=q.top().ord;q.pop();
if(vis[u])continue;
vis[u]=true;vec.pb(loc[u]);
if(vec.size()==k+)return ; //因为起点的前一条边没有意义,所以这里是k+1结束
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;ll cost=edge[i].val;
if(!vis[v]&&d[v].dist>d[u].dist+cost){
d[v].dist=d[u].dist+cost;
loc[v]=edge[i].ord; //记录这个点在 1--->v的最短路的最后一条边
q.push(d[v]);
}
}
}
}
int main(){
read(n);read(m);read(k);init();
rep(i,,m){
int u,v;ll w;
read(u);read(v);read(w);
addedge(u,v,w,i);addedge(v,u,w,i);
}
k=min(k,n-); //k与(n-1)进行比较
Dijkstra();printf("%d\n",k);
rep(i,,k)i==k?printf("%d\n",vec[i]):printf("%d ",vec[i]); //因为起点的前一条边没有意义,所以这里从1开始输出
}

2019-02-12

Codeforces 1076D Edge Deletion 【最短路+贪心】的更多相关文章

  1. Codeforces 1076D Edge Deletion(最短路树)

    题目链接:Edge Deletion 题意:给定一张n个顶点,m条边的带权无向图,已知从顶点1到各个顶点的最短路径为di,现要求保留最多k条边,使得从顶点1到各个顶点的最短距离为di的顶点最多.输出m ...

  2. 【CF1076D】Edge Deletion 最短路+贪心

    题目大意:给定 N 个点 M 条边的无向简单联通图,留下最多 K 条边,求剩下的点里面从 1 号顶点到其余各点最短路大小等于原先最短路大小的点最多怎么构造. 题解:我们可以在第一次跑 dij 时直接采 ...

  3. Edge Deletion CodeForces - 1076D(水最短路)

    题意: 设从1到每个点的最短距离为d,求删除几条边后仍然使1到每个点的距离为d,使得剩下的边最多为k 解析: 先求来一遍spfa,然后bfs遍历每条路,如果d[v] == d[u] + Node[i] ...

  4. 1076D Edge Deletion 【最短路】

    题目:戳这里 题意:求出1到所有点的最短路径后,把边减到小于等于k条,问保留哪些边可以使仍存在的最短路径最多. 解题思路:这题就是考求最短路的原理.比如dijkstra,用优先队列优化后存在队列中的前 ...

  5. Codeforces Round #303 (Div. 2) E. Paths and Trees 最短路+贪心

    题目链接: 题目 E. Paths and Trees time limit per test 3 seconds memory limit per test 256 megabytes inputs ...

  6. Codeforces 437C The Child and Toy(贪心)

    题目连接:Codeforces 437C  The Child and Toy 贪心,每条绳子都是须要割断的,那就先割断最大值相应的那部分周围的绳子. #include <iostream> ...

  7. Codeforces Round #546 (Div. 2) D 贪心 + 思维

    https://codeforces.com/contest/1136/problem/D 贪心 + 思维 题意 你面前有一个队列,加上你有n个人(n<=3e5),有m(m<=个交换法则, ...

  8. Educational Codeforces Round 54 (Rated for Div. 2) D:Edge Deletion

    题目链接:http://codeforces.com/contest/1076/problem/D 题意:给一个n个点,m条边的无向图.要求保留最多k条边,使得其他点到1点的最短路剩余最多. 思路:当 ...

  9. Codeforces Round #303 (Div. 2)(CF545) E Paths and Trees(最短路+贪心)

    题意 求一个生成树,使得任意点到源点的最短路等于原图中的最短路.再让这个生成树边权和最小. http://codeforces.com/contest/545/problem/E 思路 先Dijkst ...

随机推荐

  1. 使用open live writer客户端写博客

    注:Windows Live Writer 已经停止更新,建议安装 Open Live Writer,下载地址: http://openlivewriter.org/ 使用open live writ ...

  2. android 使用opencv

    1.将已有的项目名称改名字,但一直报错 Error:A problem occurred configuring project ':app'.> executing external nati ...

  3. javaScript遍历对象、数组总结

        javaScript遍历对象总结 1.使用Object.keys()遍历 返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性). var obj = {'0':'a ...

  4. 《剑指offer》顺时针打印矩阵

    本题来自<剑指offer> 顺时针打印矩阵 题目: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 1 ...

  5. 《剑指offer》旋转数组中的最小数字

    本题来自<剑指offer> 旋转数组中的最小数字 题目: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例 ...

  6. Spring JDBC概述

    1.jdbc 概述 Spring JDBC是Spring框架的持久层子框架.用于对数据库的操作(增删改查). 而JdbcTemplate它是spring jdbc子框架中提供的一个操作类,用于对原始J ...

  7. 高斯消元-poj1222熄灯问题状态压缩解法

    有点自闭的..为什么我最后的答案是倒着来的啊.. 搞明白了:因为一开始构造的系数就是反着的,,所以主元也倒过来了.. #include<iostream> #include<cstd ...

  8. hdu2121 最小树形图的虚根

    /* 最小树形图的第二题,终于有了一些理解 具体看注释 */ /* 无定根的最小树形图 建立虚root 每次只找最短的那条入边 最小树形图理解: 第一步:寻找最短弧集E:扫一遍所有的边,找到每个点权值 ...

  9. 存储区域网络(Storage Area Network,简称SAN)

    存储区域网络(Storage Area Network,简称SAN)采用网状通道(Fibre Channel ,简称FC,区别与Fiber Channel光纤通道)技术,通过FC交换机连接存储阵列和服 ...

  10. 使用android-ndk官方ndkbuild例子

    Why this blog 现在(2018年9月27日),Android Studio中新建ndk项目都使用cmake而不是Android.mk+Application.mk的方式.但老项目需要维护, ...