• 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

  • 相关阅读:
    STM32.ADC
    电源方案集
    什么叫二级域名
    android驱动学习---led实验
    Get,Post和Head具体解释
    Android 编码规范
    VC:当前不会命中断点,还没有为该文档载入不论什么符号
    经常使用的结构体
    【Facebook的UI开发框架React入门之九】button简单介绍(iOS平台)-goodmao
    记录遇到的ios下的bugs[废弃]
  • 原文地址:https://www.cnblogs.com/00isok/p/10366087.html
Copyright © 2020-2023  润新知