Educational Codeforces Round 54 D
阿新 • • 發佈:2018-12-21
題意:
給定n個點,m條邊的無向連通圖,定義d[j]為1號結點到j結點的最短距離
讓你刪去一些邊,讓邊數剩餘最多為k條,如果刪邊前後的兩個圖中d[j]相同的話,那j結點就是good點,
給定的邊編號1~m,現在讓你給出一種刪邊方案,是的good點儘量多;
思路:
單原點最短路,我們知道剩下的邊數e,最大是min(n-1, k);
其實不用管剩餘多少條邊,按照dijkstra求最短路的過程,把前面訪問到的e條邊放進答案裡就是了;因為這樣訪問到的邊連線的點就是原圖中的最短路,現在選出來也是最短路;
#include<bits/stdc++.h> using namespace std; #define out fflush(stdout); #define fast ios::sync_with_stdio(0),cin.tie(0); #define FI first #define SE second typedef long long ll; typedef pair<ll,ll> P; const int maxn = 3e5 + 7; const ll INF = 0x3f3f3f3f3f3f3f3f; const ll mod = 998244353; ll n, m, k; ll u, v, c; struct no { ll u, c, id; }; vector<no> vec[maxn]; struct node { ll d, v, id; bool operator< (const node &a) const { return (d > a.d); } }; priority_queue<node> qu; bool vis[maxn]; set<ll> ans; int main() { scanf("%lld%lld%lld", &n, &m, &k); for(int i = 1; i <= m; ++i) { scanf("%lld%lld%lld", &u, &v, &c); vec[u].push_back(no{v, c, i}); vec[v].push_back(no{u, c, i}); } for(auto i : vec[1]) { qu.push(node{i.c, i.u, i.id}); } vis[1] = 1; int anss = k; while(1) { if(qu.empty()) break; node t = qu.top(); qu.pop(); ll u = t.v, d = t.d, id = t.id; if(vis[u]) continue; vis[u] = 1; if(k) { k--; ans.insert(id); } for(auto i : vec[u]) { if(vis[i.u]) continue; qu.push(node{d+i.c, i.u, i.id}); } } cout << ans.size() << endl; int t = 0; for(auto i : ans) { t++; printf("%lld", i); if(t == ans.size()) break; printf(" "); } return 0; }