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

题目: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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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];
vectorint,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_queueint> > pq;
    pq.push(make_pair(dis[id][st]=0,st));
    while(!pq.empty())
    {
        int u=pq.top().second;
        pq.pop();
        for(int j=0;jint> 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;
}

你可能感兴趣的:(图论——最短路)