给巧克力【SPFA】

题目大意:
给出一个无向图,求给出的MST 经过1号点 的最短路。
Input

6 7 3 
1 2 3 
5 4 3 
3 1 1 
6 1 9 
3 4 2 
1 4 4 
3 2 2 
2 4 
5 1 
3 6 

Output

6 
6 
10 

思路:
首先,最朴素的想法,求S到点1的最短路,再求点1到T的最短路。时间复杂度O(m×ke)m为一个玄学的较大常数。直接放弃。
然后,经过一波思(瞎)考(搞),终于发现这是个无向图,然后经过严谨的思维推理,得出S到点1的最短路其实就是从点1到S的最短路!
请证明。

证明:
这还用说吗?无向图两点相互的最短路不是一样的吗?
证毕。

那么我们就从点1跑SPFA,将S看做T1T看做T2,求出dis[t1]+dis[t2]就可以了。


代码:

#include <cstdio>
#include <iostream>
#include <queue>
using namespace std;

const int inf=99999999;
int n,m,k,r,t1,t2,s,dis[200001],vis[200001],head[200001],d,x,y,sum;

struct edge  //结构体
{
    int to,dis,next;
}e[200001];

void add(int from,int to,int d)  //邻接表
{
    r++;
    e[r].dis=d;
    e[r].to=to;
    e[r].next=head[from];
    head[from]=r;
}

void spfa()  //跑最短路
{
    queue<int> q;
    for (int i=1;i<=n;i++)  //初始化
    {
        vis[i]=0;
        dis[i]=inf;
    }
    q.push(s);  //就是将点1插入
    vis[s]=1;
    dis[s]=0;
    while (q.size())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for (int i=head[u];i;i=e[i].next)  
        {
            int v=e[i].to;
            if (dis[v]>dis[u]+e[i].dis)  //更新最短路
            {
                dis[v]=dis[u]+e[i].dis;
                if (!vis[v])
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
}

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&d);
        add(x,y,d);
        add(y,x,d);  //无向图
    }
    s=1;
    spfa();
    for (int j=1;j<=k;j++)  //k问
    {
        sum=0;
        scanf("%d%d",&t1,&t2);
        sum+=dis[t1];
        sum+=dis[t2];
        printf("%d\n",sum);
    }
    return 0;
}
posted @ 2018-07-05 21:18  全OI最菜  阅读(95)  评论(0编辑  收藏  举报