Wannafly 挑战赛第二场 B Travel【最短路 建图】

来源:互联网 发布:centos解压war包 编辑:程序博客网 时间:2024/06/07 21:49

题目:https://www.nowcoder.com/acm/contest/17/B
题意:
题目描述
精灵王国有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行每行一个正整数表示该次旅行的最短时间。

wls的题解:
通过一些观察可得:节点 u 到节点 v 的最短路肯定为以下两种情况之一: 1、不经过额外的 m 条边直接从 u 到 v。
2、从 u 先走到某个为额外边端点的 x,再从 x 走到某个同样为额外边端点的 y,最后从
y 走到 v。
预处理所有额外边的端点间两两最短路,询问时暴力枚举 x、y 更新答案即可。
时间复杂度:O(M3 +N+Q× M3)。

代码:

#include <iostream>#include <algorithm>#include <string>#include <vector>#include <map>#include <set>#include <queue>#include <cstdio>#include <cstring>#include <cmath>using namespace std;typedef long long ll;const int MAXN=100005;const int MAXM=25;const ll INF=(1LL<<60)-1;int u[MAXM],v[MAXM],key[MAXM<<1];ll d[MAXN],p[MAXN],w[MAXM];vector<pair<int,ll> > e[MAXN];ll dis[MAXM<<1][MAXN];void Dijkstra(int id,int n){    int st=key[id];    for(int i=1;i<=n;i++)        dis[id][i]=INF;    priority_queue<pair<ll,int> > pq;    pq.push(make_pair(dis[id][st]=0,st));    while(!pq.empty())    {        int u=pq.top().second;        pq.pop();        for(int j=0;j<e[u].size();j++)        {            pair<ll,int> t=e[u][j];            int v=t.first,c=t.second;            if(dis[id][v]>dis[id][u]+c)            {                dis[id][v]=dis[id][u]+c;                pq.push(make_pair(-dis[id][v],v));            }        }    }}int main(){    int n,m;    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)    {        scanf("%lld",&d[i]);        e[i].push_back(make_pair(i%n+1,d[i]));        e[i%n+1].push_back(make_pair(i,d[i]));    }    for(int i=1;i<=n;i++)        p[i]=p[i-1]+d[i];    for(int i=1;i<=m;i++)    {        scanf("%d%d%lld",&u[i],&v[i],&w[i]);        e[u[i]].push_back(make_pair(v[i],w[i]));        e[v[i]].push_back(make_pair(u[i],w[i]));    }    int c=0;    for(int i=1;i<=m;i++)        key[++c]=u[i],key[++c]=v[i];    sort(key+1,key+c+1);    c=unique(key+1,key+c+1)-(key+1);    for(int i=1;i<=c;i++)        Dijkstra(i,n);    int q;    scanf("%d",&q);    for(int i=1;i<=q;i++)    {        int x,y;        scanf("%d%d",&x,&y);        ll len=abs(p[x-1]-p[y-1]);        ll res=min(len,p[n]-len);        for(int j=1;j<=c;j++)            res=min(res,dis[j][x]+dis[j][y]);        printf("%lld\n",res);    }    return 0;}
原创粉丝点击