codeforces-1343E(貪心+BFS)
阿新 • • 發佈:2020-07-27
Weights Distributing
題目連結:https://codeforces.com/contest/1343/problem/E
題目描述:
給定n個點m條無向邊,再給你a,b,c三個點和m個值,現在要求你將這m個值分配這m條邊,使a->b->c的路徑的權值最小
思路:
分類討論,一種情況是a->b和b->c這兩條路上無交點,這樣直接將權值排序後取最小即可,第二種就是兩條路上有交點,這時候我們一定可以找到一個交點x,該交點把路徑分為a->x,x->b,b->x,x->c這四段路線,因為b->x和x->b本質上是同一條路,所以我們需要優先把較小的權值分配給這條路,可以先用bfs求出a、b、c三個點到所有點的單位距離,接著貪心賦值即可。
程式碼:
#include<bits/stdc++.h> using namespace std; using ll = long long; const int INF = 0x3f3f3f3f; const ll N = 1e6; const double PI = acos(-1.0); #define Test ll tesnum;tesnum = read();while(tesnum--) ll read(); ll val[N]; vector<int> g[N]; void bfs(int id,vector<int> &v) { v[id] = 0; queue<int> q; q.push(id); while(!q.empty()){ int u = q.front(); q.pop(); for(int nx:g[u]){ if(v[nx]==INF){ v[nx] = v[u]+1; q.push(nx); } } } } int main() { Test{ int n,m,a,b,c; cin>>n>>m>>a>>b>>c; for(int i = 1; i <= m; i++){ cin>>val[i]; } for(int i = 1; i <= n; i++)g[i].clear(); sort(val+1,val+1+m); for(int i = 1; i <= m; i++){ int u,v; cin>>u>>v; g[u].push_back(v); g[v].push_back(u); val[i] += val[i-1]; } vector<int> disa(n+1,INF); vector<int> disb(n+1,INF); vector<int> disc(n+1,INF); bfs(a,disa); bfs(b,disb); bfs(c,disc); ll ans = 2e16; for(int i = 1; i <= n; i++){ if(disa[i]+disb[i]+disc[i]>m)continue; ans = min(ans,val[disb[i]]+val[disa[i]+disb[i]+disc[i]]); } cout<<ans<<endl; }; return "BT7274", NULL; } inline ll read() { ll hcy = 0, dia = 1;char boluo = getchar(); while (!isdigit(boluo)) {if (boluo == '-')dia = -1;boluo = getchar();} while (isdigit(boluo)) {hcy = hcy * 10 + boluo - '0';boluo = getchar();} return hcy * dia; }