mirror of
https://github.com/Kiritow/OJ-Problems-Source.git
synced 2024-03-22 13:11:29 +08:00
113 lines
2.7 KiB
C++
113 lines
2.7 KiB
C++
|
/**
|
|||
|
SCU - 4444 别样最短路径-大数据完全图
|
|||
|
题目大意:给定一个完全图,其中有两种边,长度为a(不超过5e5)或长度为b(剩下的),求有1~n的最短路径(数据范围1e5)
|
|||
|
解题思路:如果1和n之间连边为a那么答案一定为a和一条最短的全由b组成的路径的较小者,如果1和n之间连边为b,那么答案一定
|
|||
|
为b和一条最短的全由a组成的路径的较小者。对于第1种情况直接跑spfa就可以了,第二种情况由于边数较多,不能直接spfa
|
|||
|
从1开始搜索与其相连的边权为b的边,用set维护一下,由于每个点只入队1次,复杂度还是允许的。这种处理方法还是第一
|
|||
|
次做,感觉很巧妙
|
|||
|
*/
|
|||
|
#include <stdio.h>
|
|||
|
#include <string.h>
|
|||
|
#include <iostream>
|
|||
|
#include <algorithm>
|
|||
|
#include <set>
|
|||
|
#include <queue>
|
|||
|
using namespace std;
|
|||
|
typedef long long LL;
|
|||
|
const int INF=1e9+7;
|
|||
|
const int maxn=100100;
|
|||
|
int n,m,vis[maxn];
|
|||
|
LL a,b,dis[maxn];
|
|||
|
set<int>st,ts;
|
|||
|
set<int>::iterator it;
|
|||
|
int head[maxn],ip;
|
|||
|
void init()
|
|||
|
{
|
|||
|
memset(head,-1,sizeof(head));
|
|||
|
ip=0;
|
|||
|
}
|
|||
|
struct note
|
|||
|
{
|
|||
|
int v,next;
|
|||
|
}edge[maxn*10];
|
|||
|
void addedge(int u,int v)
|
|||
|
{
|
|||
|
edge[ip].v=v,edge[ip].next=head[u],head[u]=ip++;
|
|||
|
}
|
|||
|
void spfa()
|
|||
|
{
|
|||
|
queue<int>q;
|
|||
|
for(int i=0;i<=n;i++)dis[i]=INF;
|
|||
|
memset(vis,0,sizeof(vis));
|
|||
|
dis[1]=0;
|
|||
|
q.push(1);
|
|||
|
while(!q.empty())
|
|||
|
{
|
|||
|
int u=q.front();
|
|||
|
q.pop();
|
|||
|
vis[u]=0;
|
|||
|
for(int i=head[u];i!=-1;i=edge[i].next)
|
|||
|
{
|
|||
|
int v=edge[i].v;
|
|||
|
if(dis[v]>dis[u]+1)
|
|||
|
{
|
|||
|
dis[v]=dis[u]+1;
|
|||
|
if(!vis[v])
|
|||
|
{
|
|||
|
vis[v]=1;
|
|||
|
q.push(v);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
printf("%lld\n",min(dis[n]*a,b));
|
|||
|
}
|
|||
|
void bfs()
|
|||
|
{
|
|||
|
dis[n]=INF;
|
|||
|
st.clear(),ts.clear();
|
|||
|
for(int i=2;i<=n;i++)st.insert(i);
|
|||
|
queue<int>q;
|
|||
|
q.push(1);
|
|||
|
dis[1]=0;
|
|||
|
while(!q.empty())
|
|||
|
{
|
|||
|
int u=q.front();
|
|||
|
q.pop();
|
|||
|
for(int i=head[u];i!=-1;i=edge[i].next)
|
|||
|
{
|
|||
|
int v=edge[i].v;
|
|||
|
if(st.count(v)==0)continue;
|
|||
|
st.erase(v),ts.insert(v);
|
|||
|
}
|
|||
|
for(it=st.begin();it!=st.end();it++)
|
|||
|
{
|
|||
|
q.push(*it);
|
|||
|
dis[*it]=dis[u]+1;
|
|||
|
}
|
|||
|
st.swap(ts);
|
|||
|
ts.clear();
|
|||
|
}
|
|||
|
printf("%lld\n",min(dis[n]*b,a));
|
|||
|
}
|
|||
|
int main()
|
|||
|
{
|
|||
|
while(~scanf("%d%d%lld%lld",&n,&m,&a,&b))
|
|||
|
{
|
|||
|
init();
|
|||
|
int flag=0;
|
|||
|
for(int i=0;i<m;i++)
|
|||
|
{
|
|||
|
int u,v;
|
|||
|
scanf("%d%d",&u,&v);
|
|||
|
if(u>v)swap(u,v);
|
|||
|
addedge(u,v);
|
|||
|
addedge(v,u);
|
|||
|
if(u==1&&v==n)flag=1;
|
|||
|
}
|
|||
|
if(flag)bfs();
|
|||
|
else spfa();
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|