【GJOI 2023.10.6 T2】 亿只只因的回家路

亿只只因的回家路

题意:给出一个 \(n\)\(m\) 边的无向图,每条边有长度 \(v_i\) , 有 \(k\) 只小鸡,第 \(i\) 只小鸡在 \(id_i\) 号节点,鸡妈妈在 \(1\) 号点,现鸡妈妈要接所有的小鸡,小鸡与鸡妈妈的速度为 \(1\) ,问最短多久鸡妈妈才能接到所有的小鸡 ,\(n \le 10^5,k \le 2 \times 10^5\)
由于他们的速度都是 \(1\) ,所以可以看到他们都会集中到一个汇合点。
转化成他们到一个点的最短时间是多少。
由于这个点可能在边上,所以我们需要分类讨论。
找出这堆鸡到每个点的最短距离,时间复杂度 \(O(knlogn)\)
枚举点很简单,如何处理点在边上的情况呢?
首先,每只鸡肯定都是从边的两端进一条边的。
由于只需考虑最晚时间,所以只用找从两端进最晚的哪只鸡。
不可以贪心选最小。
我们这样考虑:将每只小鸡按从左端进的时间排序,若最晚的是第 \(i\) 只小鸡,可见 \(i\) 前的都走 \(i\) 是最优选择。
那后面的都要走右边,找出枚举找最优解即可。
时间复杂度 \(O(knlogn + mklogk)\)

Code

#include<bits/stdc++.h>
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline") 
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
using namespace std;
struct datay
{
	int x;
	int y;
}b[25];
bool operator<(const datay &q,const datay &w)
{
	return q.y>w.y;
}
priority_queue<datay> l;
int n,m,de[25],start;
int f[100005],dis[25][100005];
vector<int> a[100005];
vector<int> t[100005];
bool v[100005];
bool cmp1(datay q,datay w)
{
	return q.x<w.x;
}
int h;
char c;
int read()
{
	h=0;
	c=getchar();
	while((c<'0'||c>'9'))c=getchar();
	while(c>='0'&&c<='9')h=h*10+c-'0',c=getchar();
	return h;
}
void dij()
{
	for(register int i=1;i<=n;++i)f[i]=1e9+5;
	memset(v,false,sizeof(v)); 
	f[start]=0;
	datay q,w;
	q.x=start;
	q.y=0;
	l.push(q);
	while(l.size()!=0)
	{
		q=l.top();
		l.pop();
		if(v[q.x])continue;
		v[q.x]=true;
		for(int i=0;i<a[q.x].size();i++)
		{
			w.x=a[q.x][i];
			w.y=q.y+t[q.x][i];
			if(w.y<f[w.x])l.push(w);
			f[w.x]=min(f[w.x],w.y);
		}
	}
	return;
}
int main()
{
	int x,y;
	int z;
	n=read();
	m=read();
	for(int i=1;i<=m;i++)
	{
		x=read();
		y=read();
		z=read();
		a[x].push_back(y);
		a[y].push_back(x);
		t[x].push_back(z);
		t[y].push_back(z);
	}
	m=read();
	for(int i=1;i<=m;i++)
	{
		de[i]=read();
		start=de[i];
		dij();
		for(int j=1;j<=n;j++)dis[i][j]=f[j];
	}
	m++;
	de[m]=1;
	start=de[m];
	dij();
	for(register int i=1;i<=n;i++)dis[m][i]=f[i];
	int s=1e9+5,p=0,q,w,e;
	for(register int i=1;i<=n;i++)
	{
		p=0;
		for(int j=1;j<=m;j++)p=max(p,dis[j][i]);
		s=min(s,p*2);
	}
	for(register int qwe=1;qwe<=n;qwe++)
	{
		for(int rty=0;rty<a[qwe].size();rty++)
		{
			x=qwe;
			y=a[qwe][rty];
			z=t[qwe][rty];
			p=0;
			for(int i=1;i<=m;i++)b[i].x=dis[i][x],b[i].y=dis[i][y];
			sort(b+1,b+m+1,cmp1);
			for(int i=m-1;i>=1;i--)
			{
				b[i].y=max(b[i].y,b[i+1].y);
			}
			for(int i=m-1;i>=1;i--)
			{
				q=b[i].x;
				w=b[i+1].y;
				e=abs(q-w);
				s=min(s,(max(q,w)*2)+(z-e>0?z-e:0));
			}
		}
	}
	printf("%d",s);








  return 0;
}
posted @ 2023-10-07 19:34  dijah  阅读(25)  评论(0编辑  收藏  举报