Educational Codeforces Round 54 (Rated for Div. 2) D. Edge Deletion
阿新 • • 發佈:2018-12-21
因為di定義為是圖上1到i點的最短路徑的長度,如果不限制邊數,那麼最少需要就是n - 1條邊,使得n個點用最短路徑邊連起來,迪傑斯特拉就是用已知最短路的點去更新其他點,那麼其他點的最短路一定會經過已知最短路的點,題中要求留k條邊good點最多,那肯定是最短路上的點,k是1,有兩個good點,k為2,有三個good點,。。。。類推下去,k >= n - 1,有n個good點,所以只要用迪傑斯特拉跑一遍最短路找到路徑上的邊即可,只需找到前k個(k < n - 1) 或n - 1個邊;
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int inf = 0x3f3f3f3f; #define mp make_pair #define pb push_back #define fi first #define se second const int N = 3 * 1e5 + 5; LL dis[N]; bool vis[N]; vector<pair<int,pair<int,int> > >ve[N]; typedef struct Node{ LL w; int x,id; friend bool operator < (const Node &p,const Node &q) { return p.w > q.w; } }Node; priority_queue<Node>que; vector<int>ans; int main() { int n,m,k; scanf("%d %d %d",&n,&m,&k); for(int i = 1;i <= m;++i){ int u,v,w; scanf("%d %d %d",&u,&v,&w); ve[u].pb(mp(w,mp(v,i))); ve[v].pb(mp(w,mp(u,i))); } memset(dis,inf,sizeof(dis)); memset(vis,false,sizeof(vis)); dis[1] = 0; que.push((Node){0,1,0}); while(!que.empty()) { Node tmp = que.top(); que.pop(); if(vis[tmp.x]) continue; vis[tmp.x] = true; if(tmp.id) ans.pb(tmp.id); if(ans.size() == n - 1 || ans.size() == k) break; int len = ve[tmp.x].size(); for(int i = 0;i < len;++i){ int v = ve[tmp.x][i].se.fi; int id = ve[tmp.x][i].se.se; LL w = ve[tmp.x][i].fi; if(!vis[v] && dis[tmp.x] + w < dis[v]){ dis[v] = dis[tmp.x] + w; que.push((Node){dis[v],v,id}); } } } printf("%d\n",ans.size()); for(int i = 0;i < ans.size();++i){ printf("%d ",ans[i]); } printf("\n"); return 0; }