Codeforces 1076D Edge Deletion(最短路树)

题目链接:Edge Deletion

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

题解:先跑一遍最短路,在松弛操作时,存父子关系和边,在以这些关系建立新图(树),因为在松弛操作时存的关系,所以能保证是最短路径,最后DFS输出k条边即可。

 1 #include <queue>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 
 6 typedef long long ll;
 7 const int N=3e5+10;
 8 
 9 struct qnode{
10     ll v,w;
11     qnode(){}
12     qnode(ll v,ll w):v(v),w(w){}
13     bool operator < (const qnode& b) const{
14         return w>b.w;
15     }
16 };
17 
18 struct node{
19     ll nxt,v,w;
20     node(){}
21     node(ll nxt,ll v,ll w):nxt(nxt),v(v),w(w){}
22 };
23 
24 ll n,m,k,tot;
25 node edge[N<<1];
26 ll head[N],d[N];
27 qnode cur,tmp;
28 bool vis[N];
29 priority_queue <qnode> Q;
30 pair <ll,ll> fa[N];
31 vector <int> g[N],ans;
32 
33 void add_edge(ll u,ll v,ll w){
34     edge[tot]=node(head[u],v,w);
35     head[u]=tot++;
36 }
37 
38 void init(){
39     tot=1;
40     memset(head,0,sizeof(head));
41 }
42 
43 void dijkstra(ll s){
44     for(int i=0;i<N;i++) d[i]=1e18;
45     d[s]=0;
46     Q.push(qnode(s,0));
47     while(!Q.empty()){
48         cur=Q.top();
49         Q.pop();
50         ll u=cur.v;
51         if(vis[u]) continue;
52         vis[u]=true;
53         for(ll i=head[u];i;i=edge[i].nxt){
54             ll v=edge[i].v;
55             ll w=edge[i].w;
56             if(d[u]+w<d[v]){
57                 d[v]=d[u]+w;
58                 fa[v]=make_pair(u,(i+1)/2);
59                 Q.push(qnode(v,d[v]));
60             }
61         }
62     }
63 }
64 
65 void dfs(int u){
66     if(k==0) return;
67     if(u!=1){
68         ans.push_back(fa[u].second);
69         k--;
70     }
71     for(ll v:g[u]) dfs(v);
72 }
73 
74 int main(){
75     init();
76     scanf("%lld%lld%lld",&n,&m,&k);
77     for(ll i=1;i<=m;i++){
78         ll u,v,w;
79         scanf("%lld%lld%lld",&u,&v,&w);
80         add_edge(u,v,w);
81         add_edge(v,u,w);
82     }
83     dijkstra(1);
84     for(ll i=2;i<=n;i++) g[fa[i].first].push_back(i);
85     dfs(1);
86     printf("%d\n",ans.size());
87     for(ll u:ans) printf("%lld ",u);
88     printf("\n");
89     return 0;
90 }
View Code

 

posted @ 2018-11-14 18:14  pavtlly  阅读(284)  评论(0编辑  收藏  举报