SCU - 4444 别样最短路径-大数据完全图

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=184147

Travel

The country frog lives in has n towns which are conveniently numbered by 1,2,…,n.
Among n(n−1)2 pairs of towns, m of them are connected by bidirectional highway, which needs a minutes to travel. The other pairs are connected by railway, which needs b minutes to travel.
Find the minimum time to travel from town 1 to town n.

Input

The input consists of multiple tests. For each test:
The first line contains 4 integers n,m,a,b (2≤n≤105,0≤m≤5⋅105,1≤a,b≤109). Each of the following m lines contains 2integers ui,vi, which denotes cities ui and vi are connected by highway. (1≤ui,vi≤n,ui≠vi).

Output

For each test, write 1 integer which denotes the minimum time.

Sample Input

3 2 1 3
1 2
2 3
3 2 2 3
1 2
2 3

Sample Output

2
3

题意:

给定一个完全图,其中有两种边,长度为a(不超过5e5)或长度为b(剩下的),求有1~n的最短路径(数据范围1e5)

#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstring>
#include<set>
using namespace std;
#define inf 0x3f3f3f3f
struct node
{
    int v,val;
    node(int w,int x):v(w),val(x) {}
    bool friend operator<(const node a,const node b)
    {
        return a.val>b.val;
    }
};
struct Egda 
{
    int v,val,next;
}eadg[1000010];
int head[1000010],p;
int n,m,a,b;
inline void add(int u,int v,int val)
{
    eadg[p].v=v;
    eadg[p].val=val;
    eadg[p].next=head[u];
    head[u]=p++;
}
int dis[1000010];
int vis[1000010];
void dijk()
{
    priority_queue<node>q;
    memset(dis,inf,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[1]=0;
    q.push(node(1,dis[1]));
    while(!q.empty())
    {
        node ss=q.top();
        q.pop();
        if(vis[ss.v]) continue;
        vis[ss.v]=1;
        for(int i=head[ss.v];~i;i=eadg[i].next)
        {
            if(!vis[eadg[i].v]&&dis[eadg[i].v]>dis[ss.v]+eadg[i].val)
            {
                dis[eadg[i].v]=dis[ss.v]+eadg[i].val;
                q.push(node(eadg[i].v,dis[eadg[i].v]));
            }
        }
    }
    cout<<(dis[n]<b?dis[n]:b)<<endl;
}
void bfs()
{

    dis[1]=0;
    dis[n]=inf;
    set<int>q,e;
    set<int>::iterator it; 
    q.clear();
    e.clear();
    for(int i=2;i<=n;i++)
    q.insert(i);
    queue<int>qq;

    qq.push(1);
    while(!q.empty())
    {
        int o=qq.front();
        qq.pop();
        for(int i=head[o];~i;i=eadg[i].next)
        {
            if(q.count(eadg[i].v)) 
            {
                q.erase(eadg[i].v);
                e.insert(eadg[i].v);
            }

        }
         for(it=q.begin();it!=q.end();it++)
         {
            dis[*it]=dis[o]+1;
            qq.push(*it);
         }
         q=e;
         e.clear();

    }
    cout<<(a<dis[n]*b?a:dis[n]*b)<<endl;



}
int main()
{
    while(cin>>n>>m>>a>>b)
    {
        p=0;
        memset(head,-1,sizeof(head));
        int flag=0;
        for(int i=0;i<m;i++)
        {
            int u,v,val=a;
            cin>>u>>v;
            if(u>v) swap(u,v);
            add(u,v,val);
            add(v,u,val);
            if(u==1&&v==n) flag=1;
        }
        if(a==b) cout<<a<<endl;
        else    if(!flag)
        {
            dijk();
        }
        else
        {
            bfs();
        }
    }






    return 0;
}

这道题很6,set用的很巧妙。

这道题分两种情况

1. 1-n没有直连的公路,这个好找,直接dijk求最短路就行

2. 1-n没有公路,如果我们直接求由于情况多不行,(为啥不行,我也不知道。。),所以用set来存下无法用铁路到达的点,然后更新这些点,(bfs)dis存的是通过多少次铁路能从1到达那个点(太神奇了。。)
好6的题目,大佬的想法就是神奇

最后附上我参考的大佬博客: 神奇的传送门

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值