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 }

 

posted @ 2018-05-07 13:33  qrfkickit  阅读(205)  评论(0编辑  收藏  举报