1. 程式人生 > >Educational Codeforces Round 54 D Edge Deletion(最短路樹)

Educational Codeforces Round 54 D 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 }
Code