HDU-5876 & SCU-4444 (完全图的最短路)

来源:互联网 发布:软件可靠性定义 编辑:程序博客网 时间:2024/06/04 04:18

完全图求最短路(各边权值必须得相同),n稍大点边肯定就存不下了,这儿有一种bfs的做法:

维护两个集合,st1代表当前点能够到达的所有点的集合,和st2代表不能到达的所有点的集合。

BFS搜索,选取当前点,然后将所有与该点相连的点从st1中删去,并添加到st2。然后再拓展st1中的点,将之入

队,并将st1和st2两个集合进行交换(因为已经拓展完的肯定就是最短的了嘛,只需要拓展没到达的)。


HDU-5876

题意:n个点的完全无向图(权值均为1),从中删除m条边,给定一个S,求S到其它n-1个点的最短距离。

代码:

#include <iostream>#include <string.h>#include <cstdio>#include <set>using namespace std;const int inf = 0x3f3f3f3f;const int maxn = 200005;const int maxm = 20005;const int M = maxn*10;struct node{int v, next;}edge[maxm*2];int dis[maxn], head[maxn], q[M+5];int n, m, no, s;set<int> st1, st2;set<int>::iterator it;inline void init(){no = 0;memset(head, -1, sizeof head);memset(dis, 0x3f, sizeof dis);}inline void add(int u, int v){edge[no].v = v; edge[no].next = head[u];head[u] = no++;}void bfs(){int front, tail;front = tail = 0;st1.clear(); st2.clear();for(int i = 1; i <= n; ++i)if(i != s) st1.insert(i);q[tail++] = s; dis[s] = 0;while(front < tail){int u = q[front++];front %= M;int k = head[u];while(k != -1){if(st1.count(edge[k].v)){st1.erase(edge[k].v);st2.insert(edge[k].v);}k = edge[k].next;}for(it = st1.begin(); it != st1.end(); ++it){q[tail++] = *it;tail %= M;dis[*it] = dis[u]+1;}st1.swap(st2);st2.clear();}}int main(){int t, u, v;scanf("%d", &t);while(t--){scanf("%d %d", &n, &m);init();for(int i = 1; i <= m; ++i){scanf("%d %d", &u, &v);add(u, v); add(v, u);}scanf("%d", &s);bfs(); int kkk = 0;for(int i = 1; i <= n; ++i){if(i == s) continue;if(kkk) printf(" ");if(dis[i] == inf) printf("-1");else printf("%d", dis[i]);kkk = 1;}printf("\n");}return 0;}

SCU-4444

题意:有n个城市,编号为1~n,每个城市都相互连通,其中有m对城市通过公路连通,其他的城市通过铁路连通,经过公路的时间为a,经过铁路的时间为b,问从1到达n的时间最短为多少。

思路:最短路问题,由于每个点都是相连通的,不过连通的边只有2种,那么从1走到n就可以分成2种情况:
①1和n通过铁路相连,直接到达n的时间为b,那么就要考虑是直接通过铁路用时b到达n,还是经过若干个a到达n。
②1和n通过公路相连,直接到达n的时间为a,那么就要考虑是直接通过公路用时a到达n,还是经过若干个b到达n。
①方法可直接模板最短路求解,②则需要用上述BFS方法求解。

(分析来自:http://blog.csdn.net/huangshuai147/article/details/51433352)


代码:

#include <algorithm>#include <iostream>#include <string.h>#include <cstdio>#include <queue>#include <set>using namespace std;const int inf = 0x3f3f3f3f;const int maxn = 200005;const int maxm = 500005;const int M = maxn*10;struct node{int v, w, next;bool operator<(const node x)const{return w < x.w;}}edge[maxm*2], tp;int n, m, a, b, no;int head[maxn], dis[maxn], vis[maxn], q1[M+5];priority_queue<node> q;set<int> st1, st2;set<int>::iterator it;inline void init(){no = 0;memset(head, -1, sizeof head);memset(dis, 0x3f, sizeof dis);memset(vis, 0, sizeof vis);}inline void add(int u, int v){edge[no].v = v;edge[no].next = head[u];head[u] = no++;}void DJ(){while(!q.empty()) q.pop();dis[1] = 0;q.push((node){1, 0, 0});while(!q.empty()){tp = q.top(); q.pop();if(vis[tp.v]) continue;vis[tp.v] = 1;int k = head[tp.v];while(k != -1){if(dis[edge[k].v] > dis[tp.v]+a){dis[edge[k].v] = dis[tp.v]+a;q.push((node){edge[k].v, dis[edge[k].v], 0});}k = edge[k].next;}}}void BFS(){st1.clear(); st2.clear();for(int i = 2; i <= n; ++i) st1.insert(i);int front, tail;front = tail = 0;q1[tail++] = 1;dis[1] = 0;while(front < tail){int u = q1[front++];front %= M;int k = head[u];while(k != -1){if(st1.count(edge[k].v)){st1.erase(edge[k].v); st2.insert(edge[k].v);}k = edge[k].next;}for(it = st1.begin(); it != st1.end(); ++it){q1[tail++] = *it;tail %= M;dis[*it] = dis[u]+b;}st1.swap(st2);st2.clear();}}int main(){int flag, u, v, ans;while(~scanf("%d %d %d %d", &n, &m, &a, &b)){init(); flag = 1;for(int i = 1; i <= m; ++i){scanf("%d %d", &u, &v);add(u, v); add(v, u);if(u == 1 && v == n || v == 1 && u == n) flag = 0;}if(flag) {DJ();ans = min(b, dis[n]);}else{BFS();ans = min(a, dis[n]);}printf("%d\n", ans);}return 0;}

继续加油~
原创粉丝点击