Codeforces 1076D Edge Deletion (最短路 + dfs)
阿新 • • 發佈:2020-09-09
先用Dijkstra計算出1到i的最短路d[i]。再dfs時如果 d[u] + w == d[v] 時就一直繼續向下搜尋。這些邊都可以保留
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<map> #include<queue> #include<vector> #include<string> #include<fstream> using namespace std; #define rep(i, a, n) for(int i = a; i <= n; ++ i); #define per(i, a, n) for(int i = n; i >= a; -- i); typedef long long ll; typedef pair<ll, int> PII; const int N = 300100; const int mod = 998244353; const double Pi = acos(- 1.0); const ll INF = 1e18; const int G = 3, Gi = 332748118; ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; } ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; } ll lcm(ll a, ll b) { return a * b / gcd(a, b);} bool cmp(int a, int b){ return a > b;} // int n, m, k; int head[N], cnt = 0; int nxt[N << 1], to[N << 1]; ll c[N << 1]; bool vis[N]; ll d[N]; vector<int> res; map<ll, int> mp; inline void add(ll u, ll v, ll w){ to[cnt] = v, c[cnt] = w, nxt[cnt] = head[u], head[u] = cnt ++; to[cnt] = u, c[cnt] = w, nxt[cnt] = head[v], head[v] = cnt ++; } void Dijkstra(int st){ priority_queue<PII, vector<PII>, greater<PII> > q; for(int i = 0; i <= n + 1; ++ i) d[i] = INF; d[st] = 0; q.push(PII(0, st)); while(q.size()){ int u = q.top().second; ll w1 = q.top().first ; q.pop(); if(w1 != d[u]) continue; for(int i = head[u]; i != -1; i = nxt[i]){ int v = to[i]; ll w2 = c[i]; if(d[v] > d[u] + w2){ d[v] = d[u] + w2; q.push(PII(d[v], v)); } } } } void dfs(ll u){ for(int i = head[u]; i != -1; i = nxt[i]){ ll v = to[i]; ll w = c[i]; if(vis[v]) continue; if(d[u] + w == d[v]){ vis[v] = true; res.push_back(mp[u * N + v]); dfs(v); } } } int main() { scanf("%d%d%d",&n,&m,&k); cnt = 0; for(int i = 0; i <= n; ++ i) vis[i] = false, head[i] = -1; for(int i = 1; i <= m; ++ i){ ll x, y, z; scanf("%lld%lld%lld",&x,&y,&z); add(x, y, z); mp[x * N + y] = mp[y * N + x] = i; } Dijkstra(1); vis[1] = true; dfs(1); int tt = res.size(); printf("%d\n",min(tt, k)); if(tt < k){ for(int i = 0; i < tt; ++ i) printf("%d ",res[i]); int num = k - tt; for(int i = 1; i <= n; ++ i){ if(num <= 0) break; if(!vis[i]){ if(num == 1) printf("%d\n",i); else printf("%d ",i); num --; vis[i] = true; } } } else{ for(int i = 0; i < k; ++ i){ printf("%d",res[i]); if(i == k - 1) printf("\n"); else printf(" "); } } return 0; }