列表

详情


NC236210. 传送门

描述

有 n 个点, m 种类型的传送门。每一个点上都可能有若干(可能为0)个不同类型的传送门。对于 i 类型的传送门,你可以花费 t_i 的时间移动到任意一个 i 类型的传送门。Alice初始位于1号点,Bob初始位于 n 号点,他们可以同时进行移动,并且他们希望花费尽可能少的时间移动到同一个点上,你能帮帮他们吗。

输入描述

第一行输入两个整数  ,分别表示点数和传送门类型数。

接下来 m 行,分别描述每一个类型的传送门。对于每一行,首先输入两个整数  ,分别表示穿过这个类型的传送门需要消耗的时间,以及这个类型的传送门的数量。接下来包含 S_i 个不同的正整数  ,表示这个类型的传送门分布在哪些点上。保证  。

输出描述

如果Alice和Bob不能移动到同一点上,输出一行-1。否则,输出两行,第一行表示他们需要花费的最少时间,第二行输出他们可以在保证花费时间最少的前提下可以相遇的点。如果有多个,你需要升序输出它们。

示例1

输入:

5 4
1 3 1 2 3
2 2 3 4
10 2 1 5
3 3 3 4 5

输出:

3
3 4

说明:

Alice可以用类型1的传送门,花费1的时间到达3号点,Bob用类型4的传送门,花费3的时间到达3号点。最终花费3的时间。

此外,Alice也可以用类型1的传送门先到达3号点,再用类型2的传送门花费2的时间到达4号点,Bob用类型4的传送门花费3的时间到达4号点。最终花费3的时间。

示例2

输入:

3 1
1 2 1 2

输出:

-1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 549ms, 内存消耗: 69016K, 提交时间: 2023-05-25 12:16:05

# include<bits/stdc++.h>
using namespace std;
typedef long long ll;
# define ios::ios_sync_with_stdio(0),cin.tie(0),cout.tie(0)
typedef pair<int,int> pii;
const int N=1e6+10;
int n,m;
vector<pair<int ,int >>mp[N];
int a[2*N];
int b[2*N];
int st[2*N];
int u[2*N];
void dj(int (&dis)[2*N],int start){
	memset(dis,0x3f,sizeof(dis));
	memset(st,0,sizeof(st));
	priority_queue<pii,vector<pii>,greater<pii>> q;
	q.push({0,start});
	dis[start]=0;
	while(!q.empty()){
		auto T=q.top();
		q.pop();
		int t=T.second;
		int ds=T.first;
		st[t]=1;
	//	cout<<t<<" "<<ds<<endl;
		for(auto &e:mp[t]){
			int ne=e.first;
			int w=e.second;
			if(!st[ne]&&dis[ne]>dis[t]+w){
				dis[ne]=dis[t]+w;
				q.push({dis[ne],ne});
			}
		}
	} 
}
void sove(){
	dj(a,1);
	dj(b,n);
	ll ans=0x3f3f3f3f;
	for(int i=1;i<=n;i++){
		ans=min(ans,(ll)max(a[i],b[i]));
	}
	if(ans==0x3f3f3f3f)cout<<"-1";
	else{
		cout<<ans<<endl;
		for(int i=1;i<=n;i++){
		if(ans==max(a[i],b[i])){
			cout<<i<<" ";
		}
	}
	}
	
}
signed main(){
    cin>>n>>m;
    for(int j=1;j<=m;j++){
    	int s,t;
    	cin>>t>>s;
        while(s--){
        	int tmp;
        	cin>>tmp;
        	mp[tmp].push_back({tmp,0});
        		mp[n+j].push_back({tmp,0});
        		mp[tmp].push_back({n+j,t});
		}
	}
	
	sove();
	return 0;
}

C++ 解法, 执行用时: 431ms, 内存消耗: 20748K, 提交时间: 2022-07-05 11:00:11

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int n,m;
const int N = 4e5+10,M = 2e7 + 10;
long long int dist[N],backup[N];
int h[N],e[M],ne[M],idx,w[M];
bool st[N];
typedef pair<int,int>PII;

void add(int a,int b,int c)
{
	e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}

void dijkstra(int op)
{
	memset(dist,0x3f3f3f3f,sizeof(dist));
	dist[op]=0;
	priority_queue<PII,vector<PII>,greater<PII> >q;
	q.push({0,op});
	while(!q.empty())
	{
		auto r=q.top();
		q.pop();
		int k=r.second,l=r.first;
		if(st[k])continue;
		st[k]=true;
		for(int i=h[k];i!=-1;i=ne[i])
		{
			int j=e[i];
			if(dist[j]>dist[k]+w[i])
			{
				dist[j]=dist[k]+w[i];
				q.push({dist[j],j});
			}
		}
	}
}

int main()
{
	cin>>n>>m;
	memset(h,-1,sizeof(h));
	for(int i=1;i<=m;i++)
	{
		int s,t;
		cin>>t>>s;
		while(s--)
		{
			int r;
			cin>>r;
			add(i+100000,r,t);
			add(r,i+100000,t);
		}
	}
	
	dijkstra(1);
	for(int i=1;i<=n;i++)backup[i]=dist[i];
	memset(st,false,sizeof(st));
	dijkstra(n);
	long long ans=1e18;
	for(int i=1;i<=n;i++)
	{
			ans=min(ans,max(backup[i],dist[i]));
	}
	if(ans==1e18)cout<<-1<<endl;
	else{
		cout<<ans/2<<endl;
		for(int i=1;i<=n;i++)
			if(max(backup[i],dist[i])==ans)cout<<i<<' ';
	}
	return 0;
}

上一题