题意:给定一个完全图,其中有两种边,长度为a(不超过5e5)或长度为b(剩下的),求有1~n的最短路径(数据范围1e5)。
思路:这题的答案显然分为两种情况,第一种1到n的边长为b,这时我们要求长为a的这些边从1到n的最短路,因为边长都相同,一次bfs即可。
第二种情况是1到n的边长为a,此时我们要求长为b的这些边从1到n的最短路,因为边数太多,直接bfs肯定t,
考虑用一个set维护当前剩余的未到达点,每次将set中的长为a的边到达的点删去,然后bfs即可,这样做保证了每个点只被访问一次,时间复杂度为O(n*logn)。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<ctime>
#define eps 1e-6
#define LL long long
#define pii pair<int, int>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int MAXN = 100100;
const int INF = 0x3f3f3f3f;
int n, m, a, b;
int dist[MAXN];
bool vis[MAXN];
struct Edge {
int to,next;
} edge[MAXN*10];
int head[MAXN], tot;
void init() {
tot = 0;
memset(head,-1,sizeof(head));
}
void addedge(int u, int v) {
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
LL bfs1() {
queue<int> q;
memset(vis, 0, sizeof(vis));
q.push(1);
vis[1] = 1;
while(!q.empty() && !vis[n]) {
int t = q.front(); q.pop();
for(int i = head[t]; i != -1; i = edge[i].next) {
int u = edge[i].to;
if(vis[u]) continue;
dist[u] = dist[t] + 1;
vis[u] = 1;
q.push(u);
}
}
if(!vis[n]) return INF;
else return (LL)dist[n]*a;
}
LL bfs2() {
set<int> last;
for(int i = 2; i <= n; i++) last.insert(i);
queue<int> q;
memset(vis, 0, sizeof(vis));
q.push(1);
vis[1] = 1;
while(!q.empty() && !vis[n]) {
int t = q.front(); q.pop();
set<int> tmp;
for(int i = head[t]; i != -1; i = edge[i].next) {
int u = edge[i].to;
if(vis[u]) continue;
last.erase(u);
tmp.insert(u);
}
for(set<int>::iterator it = last.begin(); it != last.end(); it++) {
int u = *it;
dist[u] = dist[t] + 1;
vis[u] = 1;
q.push(u);
}
last = tmp;
}
if(!vis[n]) return INF;
else return (LL)dist[n]*b;
}
int main() {
//freopen("input.txt", "r", stdin);
while(scanf("%d%d%d%d", &n, &m, &a, &b) == 4) {
init();
bool tag = 0;
for(int i = 1, u, v; i <= m; i++) {
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
if(u==1&&v==n || u==n&&v==1) tag = 1;
}
LL ans;
if(tag) ans = min((LL)a, bfs2());
else ans = min((LL)b, bfs1());
cout << ans << endl;
}
return 0;
}