1343E - Weights Distributing 最短路+貪心

我們通過觀察發現:

a->b->c。

爲了讓路徑最短

只會有2種情況

a->b->c

a->x->b->x->c

即b到c時會與a有重複。

顯然,有重複邊時一定是更優的,因爲這樣就能讓邊權小的多算一遍,從而少算一遍邊權大的。

直接枚舉所有點,用前綴和優化即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = 2e5+7;
int head[M],cnt;
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y,int z){ee[++cnt].nxt=head[x],ee[cnt].to=y,ee[cnt].val=z,head[x]=cnt;}
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
int n,m,a,b,c;
ll d[M],d2[M],d3[M],p[M],sm[M];
int vs[M];
priority_queue<pair<int,int> ,vector<pair<int,int> >,greater<pair<int,int> > >q;
void dij()
{
	for(int i=0;i<=n;i++)d[i]=0x3f3f3f3f,vs[i]=0;
	d[a]=0;
	q.push({d[a],a});
	while(!q.empty())
	{
		pair<int,int>  tp=q.top();q.pop();
		int u=tp.second ;
		if(vs[u])continue;
		vs[u]=1;
		for(int i=head[u];i;i=ee[i].nxt)
		{
			int v=ee[i].to,w=ee[i].val;
			if(d[v]>d[u]+w)//1經過u再到v的距離小於 1直接到v的距離 則更新距離
			d[v]=d[u]+w,q.push({d[v],v});
		}
	}
	for(int i=0;i<=n;i++)d2[i]=0x3f3f3f3f,vs[i]=0;
	d2[c]=0;
	q.push({d2[c],c});
	while(!q.empty())
	{
		pair<int,int>  tp=q.top();q.pop();
		int u=tp.second ;
		if(vs[u])continue;
		vs[u]=1;
		for(int i=head[u];i;i=ee[i].nxt)
		{
			int v=ee[i].to,w=ee[i].val;
			if(d2[v]>d2[u]+w)//1經過u再到v的距離小於 1直接到v的距離 則更新距離
			d2[v]=d2[u]+w,q.push({d2[v],v});
		}
	}
	for(int i=0;i<=n;i++)d3[i]=0x3f3f3f3f,vs[i]=0;
	d3[b]=0;
	q.push({d3[b],b});
	while(!q.empty())
	{
		pair<int,int>  tp=q.top();q.pop();
		int u=tp.second ;
		if(vs[u])continue;
		vs[u]=1;
		for(int i=head[u];i;i=ee[i].nxt)
		{
			int v=ee[i].to,w=ee[i].val;
			if(d3[v]>d3[u]+w)//1經過u再到v的距離小於 1直接到v的距離 則更新距離
			d3[v]=d3[u]+w,q.push({d3[v],v});
		}
	}
}
int nm=0;
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	int t;
	cin>>t;
	while(t--)
	{
		
		cin>>n>>m>>a>>b>>c;
	  	int x,y,z;
	  	cnt=0;
	  	for(int i=0;i<=n;i++)head[i]=0;
	  	for(int i=1;i<=m;i++)cin>>p[i];
	  	for(int i=1;i<=m;i++)cin>>x>>y,add(x,y,1),add(y,x,1);
	  	dij();
		sort(p+1,p+1+m);
		ll pr=2e18;
		for(int i=1;i<=m;i++)sm[i]=sm[i-1]+p[i];
		for(int i=1;i<=n;i++)
		{
			if(d[i]+d2[i]+d3[i]>m)continue;
			pr=min(pr,sm[d[i]+d2[i]+d3[i]]+sm[d3[i]]);
		}
		cout<<pr<<endl;
	} 
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章