• 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

  • 相关阅读:
    div相对屏幕居中
    Webstorm快捷键
    VIM快捷键
    美食 pizza 家常菜
    ln -s 软链接
    解决Linux服务器执行出现-bash: ./xxx.sh: /bin/sh^M: bad interpreter: No such file or directory
    PHP Apache 搭建FastCGI环境
    VS Code 添加php.validate.executablePath 路径
    git push 时报错 remote: The project you were looking for could not be found.
    PHP类中私有静态成员初始化
  • 原文地址:https://www.cnblogs.com/00isok/p/10366087.html
Copyright © 2020-2023  润新知