列表

详情


NC14292. Travel

描述

精灵王国有N座美丽的城市,它们以一个环形排列在Bzeroth的大陆上。其中第i座城市到第i+1座城市花费的时间为d[i]。特别地,第N座城市到第1座城市花费的时间为d[N]。这些道路都是双向的。

另外,精灵们在数千年的时间里建造了M座传送门,第i座传送门连接了城市u[i]与城市v[i],并且需要花费w[i]的时间通过(可能有两座传送门连接了同一对城市,也有可能一座传送门连接了相同的两座城市)。这些传送门都是双向的。

小S是精灵王国交通部部长,她的职责是为精灵女王设计每年的巡查路线。每次陛下会从某一个城市到达另一个城市,沿路调查每个城市的治理情况,她需要找出一条用时最短的路线。

输入描述

第一行为2个整数N、M。
第二行为N个正整数d[i]。
接下来M行每行三个正整数u[i]、v[i]、w[i]。
第M+3行为一个正整数Q,表示需要设计路线的次数。
接下来Q行每行两个正整数x、y,表示一次从城市x到城市y的旅行。

输出描述

Q行每行一个正整数表示该次旅行的最短时间。

示例1

输入:

4 1
1 2 3 6
1 3 2
5
1 2
1 4
1 3
2 3
4 3

输出:

1
5
2
2
3

原站题解

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

C++(g++ 7.5.0) 解法, 执行用时: 59ms, 内存消耗: 13424K, 提交时间: 2022-11-03 23:46:10

#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;

int n, m;
const int N = 6 * (1e4 + 5), M = N * 2;
int ne[M], e[M], h[N], w[M],
a, b, c, idx, qu;
LL sum[N];
LL dist[22][N];
queue<int>q;
bool st[N];

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

void spfa(int a, LL g[]) {
	memset(st, 0, sizeof st);
	while (q.size()) {
		int u = q.front();
		q.pop();
		st[u] = 0;
		for (int i = h[u]; ~i; i = ne[i]) {
			int son = e[i];
			if (g[son] > g[u] + w[i]) {
				g[son] = g[u] + w[i];
				if (st[son])continue;
				st[son] = 1;
				q.push(son);
			}
		}
	}
}

int main() {
	memset(h, -1, sizeof h);
	cin >> n >> m;
	memset(dist, 0x3f, sizeof dist);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a);
		if (i == n)add(i, 1, a), add(1, i, a);
		else add(i, i + 1, a), add(i + 1, i, a);
		sum[i+1] = a + sum[i];
	}
	int cnt = 0;
	while (m--) {
		scanf("%d%d%d", &a, &b, &c);
		add(a, b, c), add(b, a, c);
		dist[cnt][a] = 0;
		//dist[cnt][b] = 0;
		//q.push(b);
		q.push(a);
		spfa(cnt, dist[cnt]);
		cnt++;
	}
	cin >> qu;
	while (qu--) {
		scanf("%d%d", &a, &b);
		//没有传送门时
		if (a > b)swap(a, b);
		LL ans =  min(sum[b] - sum[a], 
				sum[n + 1] - (sum[b] - sum[a]));
		//有传送门时
		for (int i = 0; i < cnt;i++) {
			ans = min(ans, dist[i][a] + dist[i][b]);
		}
		printf("%lld\n", ans);
	}
	return 0;
}

C++14(g++5.4) 解法, 执行用时: 195ms, 内存消耗: 3092K, 提交时间: 2020-07-15 21:14:19

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m,ans,a[200010],f[101][101],sum[200010],id[200010],cnt;
map<ll,ll>mp;
ll get(ll l,ll r){
    if(l>r)swap(l,r);
    return min(sum[r-1]-sum[l-1],sum[n]-sum[r-1]+sum[l-1]);
}
int main(){
    ll t1,i,j,k,x,y,w;
    scanf("%lld%lld",&n,&m);
    for(i=1;i<=50;i++)
     for(j=1;j<=50;j++)f[i][j]=1e18;
    for(i=1;i<=n;i++)scanf("%lld",&a[i]);
    for(i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];
    for(i=1;i<=m;i++){
        scanf("%lld%lld%lld",&x,&y,&w);
        if(!mp[x])mp[x]=++cnt,id[cnt]=x;
        if(!mp[y])mp[y]=++cnt,id[cnt]=y;
        x=mp[x];y=mp[y];
        f[x][y]=f[y][x]=min(f[x][y],w);
    }
    for(i=1;i<=cnt;i++)
     for(j=1;j<=cnt;j++)f[i][j]=f[j][i]=min(f[i][j],get(id[i],id[j]));
    for(k=1;k<=cnt;k++)
     for(i=1;i<=cnt;i++)
      for(j=1;j<=cnt;j++)f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
    scanf("%lld",&t1);
    while(t1--){
        scanf("%lld%lld",&x,&y);
        ans=get(x,y);
        for(i=1;i<=cnt;i++)
         for(j=1;j<=cnt;j++)ans=min(ans,get(x,id[i])+get(y,id[j])+f[i][j]);
        printf("%lld\n",ans);
    }
}

C++11(clang++ 3.9) 解法, 执行用时: 326ms, 内存消耗: 2140K, 提交时间: 2020-01-05 15:11:07

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m,ans,a[200010],f[101][101],sum[200010],id[200010],cnt;
map<ll,ll>mp;
ll get(ll l,ll r){
	if(l>r)swap(l,r);
	return min(sum[r-1]-sum[l-1],sum[n]-sum[r-1]+sum[l-1]);
}
int main(){
	ll t1,i,j,k,x,y,w;
	scanf("%lld%lld",&n,&m);
	for(i=1;i<=50;i++)
	 for(j=1;j<=50;j++)f[i][j]=1e18;
	for(i=1;i<=n;i++)scanf("%lld",&a[i]);
	for(i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];
	for(i=1;i<=m;i++){
		scanf("%lld%lld%lld",&x,&y,&w);
		if(!mp[x])mp[x]=++cnt,id[cnt]=x;
		if(!mp[y])mp[y]=++cnt,id[cnt]=y;
		x=mp[x];y=mp[y];
		f[x][y]=f[y][x]=min(f[x][y],w);
	}
	for(i=1;i<=cnt;i++)
	 for(j=1;j<=cnt;j++)f[i][j]=f[j][i]=min(f[i][j],get(id[i],id[j]));
	for(k=1;k<=cnt;k++)
	 for(i=1;i<=cnt;i++)
	  for(j=1;j<=cnt;j++)f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
	scanf("%lld",&t1);
	while(t1--){
		scanf("%lld%lld",&x,&y);
		ans=get(x,y);
		for(i=1;i<=cnt;i++)
		 for(j=1;j<=cnt;j++)ans=min(ans,get(x,id[i])+get(y,id[j])+f[i][j]);
		printf("%lld\n",ans);
	}
}

上一题