CF1343 E. Weights Distributing

E. Weights Distributing

Question

給定由nn個點,mm條邊構成的無權無向圖和mm個權值以及三個點a,b,ca,b,c。問如何分配這mm個權值才能使 lenab+lenbclen_{a→b}+len_{b→c}最小

Solution

有兩種情況:

  1. axbxca→x→b→x→clenax+lenxb+lenbx+lenxclen_{a→x}+len_{x→b}+len_{b→x}+len_{x→c}
  2. abca→b→clenaclen_{a→c}

第二種情況是b在a→c的路上,算是1的特例,此時lenbx=0len_{b→x}=0
最優構造放權值的方法爲,xbx→b這條路上放的權值最小,因爲這條路可能要計算兩遍。
對每個點進行BFS,求其到其他點的距離,遍歷每一個點爲x的情況,記錄最小值,爲了計算路徑方便,需要對pp數組排序,然後求其前綴和。

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF  = 0x3f3f3f3f;
const ll  mod  = 1e9 + 7;
const ll  maxn = 1e6 + 5;
const int N = 2e5 + 5;

int n,m,A,B,C;
vector<int> G[N];
int dA[N],dB[N],dC[N];
ll p[N];

void bfs(int s,int *d){
	for(int i=1;i<=n;i++) d[i]=-1;
	queue<int>q;
	q.push(s);d[s]=0;
	while(!q.empty()){
		int t=q.front();q.pop();
		for(auto c:G[t]){
			if(d[c]==-1){
				d[c]=d[t]+1;
				q.push(c);
			}
		}
	}
}

void solve(){
	cin>>n>>m>>A>>B>>C;
	for(int i=1;i<=n;i++) G[i].clear();
	for(int i=1;i<=m;i++) cin>>p[i];
	sort(p+1,p+1+m);
	for(int i=1;i<=m;i++) p[i]+=p[i-1];
	for(int i=1;i<=m;i++){
		int u,v;cin>>u>>v;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	bfs(A,dA);
	bfs(B,dB);
	bfs(C,dC);
	ll ans=1ll<<60;
	for(int i=1;i<=n;i++) 
		if(dA[i]+dB[i]+dC[i]<=m)
			ans=min(ans,p[dA[i]+dB[i]+dC[i]]+p[dB[i]]);
	cout<<ans<<'\n';
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;cin>>T;
	while(T--){
		solve();
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章