2017计蒜之道复赛 百度地图导航

分析:这道题本质就是很简单的最短路问题,但是如果连边用O(n^2)的暴力会直接TLE掉,连一条边的复杂度是减少不了了,那么能不能减少连边的数量呢?

我们可以设置一个中间点p,假设a中的所有点要到b中去,则从a向p连一条有向边,p向b连一条有向边,可是这样权值不好办啊,那么我们把每个城市圈当作一个中心点,这样从a连向a',a'连向b',b'连向b,除了中间这条边以外的边权值都是0,但是我也有可能从b走向a啊,那么a到a'的两条边的边权都是0,这样会陷入死循环啊?

      解决方法很简单,我们把每个中心点拆成两个点,一个点只能进来,一个点只能出去,中心点之间的连边都从出去的点连向进来的点,跑一下最短路就好了.注意要用到long long!

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

const long long inf = 1e15;

int n,m,m1,m2,s,t,head[100010],to[200010],nextt[200010],w[200010],tot,vis[100010];
long long d[100010];

void add(int x,int y,int z)
{
    w[tot] = z;
    to[tot] = y;
    nextt[tot] = head[x];
    head[x] = tot++;
}

void spfa()
{
    for (int i = 1; i <= n + m + m; i++)
    d[i] = inf;
    queue <int> q;
    q.push(s);
    d[s] = 0;
    vis[s] = 1;
    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        vis[u] = 0;
        for (int i = head[u]; i + 1; i = nextt[i])
        {
            int v = to[i];
            if (d[v] > d[u] + w[i])
            {
                d[v] = d[u] + w[i];
                if (!vis[v])
                {
                    vis[v] = 1;
                    q.push(v);
                }
            }
        }
    }
}

int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for (int i = 1; i <= m; i++)
    {
        int k;
        scanf("%d",&k);
        for (int j = 1; j <= k; j++)
        {
            int t;
            scanf("%d",&t);
            add(t,i + n,0);
            add(i + n + m,t,0);
        }
    }
    scanf("%d",&m1);
    for (int i = 1; i <= m1; i++)
    {
        int u,v,c;
        scanf("%d%d%d",&u,&v,&c);
        add(u,v,c);
        add(v,u,c);
    }
    scanf("%d",&m2);
    for (int i = 1; i <= m2; i++)
    {
        int a,b,l;
        scanf("%d%d%d",&a,&b,&l);
        add(a + n,b + n + m,l);
        add(b + n,a + n + m,l);
    }
    scanf("%d%d",&s,&t);
    spfa();
    if (d[t] == inf)
    printf("-1
");
    else
    printf("%lld
",d[t]);
    
    return 0;
 } 
原文地址:https://www.cnblogs.com/zbtrs/p/7400098.html