zoukankan      html  css  js  c++  java
  • Codeforces 1076D Edge Deletion 【最短路+贪心】

    <题目链接>

    题目大意:

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

    解题分析:

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

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

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <queue>
     4 #include <vector>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 #define M int(3e5+10)
     9 #define rep(i,s,t) for(int i=s;i<=t;i++)
    10 #define pb push_back
    11 #define clr(a,b) memset(a,b,sizeof(a))
    12 #define INF ll(1e18)
    13 typedef long long ll;
    14 int cnt,head[M],loc[M];
    15 bool vis[M];
    16 vector<int>vec;
    17 int n,m,k;
    18 
    19 template<typename T>    
    20 inline T read(T&x){
    21     x=0;int f=0;char ch=getchar();
    22     while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar();
    23     while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    24     return x=f?-x:x;
    25 }
    26 struct Edge{
    27     int to,ord,next;
    28     ll val;
    29 }edge[M<<1];
    30 
    31 struct Node{
    32     int ord;ll dist;
    33     Node(int _ord=0,ll _dist=0):ord(_ord),dist(_dist){}
    34     bool operator < (const Node &tmp)const {
    35         return dist>tmp.dist;
    36     }
    37 }d[M];
    38 void init(){
    39     cnt=0;clr(head,-1);
    40 }
    41 void addedge(int u,int v,ll w,int c){
    42     edge[++cnt].to=v;edge[cnt].val=w,edge[cnt].ord=c;
    43     edge[cnt].next=head[u];head[u]=cnt;
    44 }
    45 void Dijkstra(){
    46     priority_queue<Node>q;
    47     for(int i=1;i<=n;i++)
    48         d[i].dist=INF,d[i].ord=i,vis[i]=false;
    49     d[1].dist=0;q.push(d[1]);
    50     while(q.size()){
    51         int u=q.top().ord;q.pop();
    52         if(vis[u])continue;
    53         vis[u]=true;vec.pb(loc[u]);
    54         if(vec.size()==k+1)return ;       //因为起点的前一条边没有意义,所以这里是k+1结束
    55         for(int i=head[u];~i;i=edge[i].next){
    56             int v=edge[i].to;ll cost=edge[i].val;
    57             if(!vis[v]&&d[v].dist>d[u].dist+cost){
    58                 d[v].dist=d[u].dist+cost;
    59                 loc[v]=edge[i].ord;       //记录这个点在 1--->v的最短路的最后一条边
    60                 q.push(d[v]);
    61             }
    62         }
    63     }
    64 }   
    65 int main(){
    66     read(n);read(m);read(k);init();
    67     rep(i,1,m){
    68         int u,v;ll w;
    69         read(u);read(v);read(w);
    70         addedge(u,v,w,i);addedge(v,u,w,i);
    71     }
    72     k=min(k,n-1);     //k与(n-1)进行比较
    73     Dijkstra();printf("%d
    ",k);
    74     rep(i,1,k)i==k?printf("%d
    ",vec[i]):printf("%d ",vec[i]);    //因为起点的前一条边没有意义,所以这里从1开始输出
    75 }

    2019-02-12

  • 相关阅读:
    【django后端分离】Django Rest Framework之一般配置(简单剖析)
    【python小随笔】celery周期任务(简单原理)
    【django后端分离】mysql原生查询命令后,RawQueryset类型的自定义序列化返回json格式
    【python小随笔】Django+错误日志(配置Django报错文件指定位置)
    luogu P3194 [HNOI2008]水平可见直线 |单调栈
    luogu P6247 [SDOI2012]最近最远点对 |随机化
    luogu P3567 [POI2014]KUR-Couriers |莫队+随机化
    P6569 [NOI Online #3 提高组]魔法值| 矩阵乘法
    luogu P1452 【模板】旋转卡壳
    luogu P3829 [SHOI2012]信用卡凸包 |凸包
  • 原文地址:https://www.cnblogs.com/00isok/p/10366087.html
Copyright © 2011-2022 走看看