scu 4444 Travel
题意:
一个完全图,有n个点,其中m条边是权值为a的无向边,其它是权值为b的无向边,问从1到n的最短路。
思路:
首先判断1和n被哪种边连通。
如果是被a连通,那么就需要全部走b的边到达n,选择最小的;
被b连通,需要走全部为a的边到达n,选择最小的。
第二种情况,用输入的边跑dijkstra;
但是第一种情况边太多,所以并不能单纯的用最短路。
可以想到的是,对于第二种情况,一个点只会经过一次。
所以用一个set来存还未访问过的点,进行bfs。
每次从队列中取出一个点x,把set中与x以a边相连的点暂时去掉,那么此时set中就是与x以b边相连并且还未访问的点了,这个时候就可以进行松弛了。
之后再对set进行更新,使其为还未访问到的点。
又犯了这个睿智错误,数据还没输入就进行处理了,真是睿智。
自定义的比较宏比algor里面得到快很多啊。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <vector> 5 #include <set> 6 #include <queue> 7 #define mi(x,y) (x) > (y) ? (y) : (x) 8 using namespace std; 9 typedef long long ll; 10 const int N = 1e5 + 10; 11 struct node 12 { 13 int to,cost; 14 node (int a,int b):to(a),cost(b){}; 15 node(){}; 16 }; 17 struct js 18 { 19 int x; 20 ll d; 21 js(int a,ll b):x(a),d(b){}; 22 js(){}; 23 bool operator < (const js& y) const 24 { 25 return y.d < d; 26 } 27 }; 28 vector<node> g[N]; 29 int n,m,a,b; 30 ll dis[N]; 31 void dij(void) 32 { 33 for (int i = 1;i <= n;i++) dis[i] = 1e18; 34 dis[1] = 0; 35 priority_queue<js> pq; 36 pq.push(js(1,0)); 37 while (!pq.empty()) 38 { 39 js t = pq.top();pq.pop(); 40 if (t.d > dis[t.x]) continue; 41 int x = t.x; 42 for (auto v:g[x]) 43 { 44 if (dis[v.to] > dis[x] + v.cost) 45 { 46 dis[v.to] = dis[x] + v.cost; 47 pq.push(js(v.to,dis[v.to])); 48 } 49 } 50 } 51 } 52 void bfs(void) 53 { 54 set<int> s,t; 55 for (int i = 2;i <= n;i++) s.insert(i); 56 queue<int> q; 57 q.push(1); 58 while (!q.empty()) 59 { 60 int x = q.front();q.pop(); 61 if (x == n) break; 62 for (auto v:g[x]) 63 { 64 if (s.count(v.to) == 0) continue; 65 s.erase(v.to); 66 t.insert(v.to); 67 } 68 for (auto y:s) 69 { 70 dis[y] = dis[x] + b; 71 q.push(y); 72 } 73 s.swap(t); 74 t.clear(); 75 } 76 } 77 int main() 78 { 79 while (scanf("%d%d%d%d",&n,&m,&a,&b) != EOF) 80 { 81 for (int i = 1;i <= n;i++) 82 { 83 g[i].clear(); 84 } 85 bool f = 0; 86 for (int i = 0;i < m;i++) 87 { 88 int x,y; 89 scanf("%d%d",&x,&y); 90 if (x > y) swap(x,y); 91 g[x].push_back(node(y,a)); 92 g[y].push_back(node(x,a)); 93 if (x == 1 && y == n) f = 1; 94 } 95 ll ans; 96 if (f) 97 { 98 bfs(); 99 ans = mi((ll)a,dis[n]); 100 } 101 else 102 { 103 dij(); 104 ans = mi((ll)b,dis[n]); 105 } 106 printf("%lld\n",ans); 107 } 108 return 0; 109 }
康复训练中~欢迎交流!