HDU 6166 Senior Pan spfa(顶点集间最短路)

来源:互联网 发布:李刚疯狂java讲义 编辑:程序博客网 时间:2024/06/06 01:04

传送门:HDU6166

题意:给出一个有向图,并给出一个点集,请求出集合中的点任意两两之间的最短距离中最小的那个。

思路:当时xjb写了一发二分 + 爆搜,果不其然TLE。。

正解:戳这里戳这里

按照二进制位分组的思路真的是很巧妙啊。

代码:

#include<bits/stdc++.h>#define ll long long#define inf 0x3f3f3f3fusing namespace std;typedef pair<int,int> P;const int MAXN = 100010;int pre[MAXN];struct node{int v, w, next;node(int _v = 0, int _w = 0, int _next = 0) : v(_v), w(_w), next(_next) {} }mp[MAXN << 1];int cnt;int dis[MAXN];bool book[MAXN];void init(int n){memset(pre, -1, sizeof(int) * (n + 2));memset(book, 0, sizeof(int) * (n + 2));memset(dis, inf, sizeof(int) * (n + 2));cnt = 0;}void addedge(int u, int v, int w){mp[cnt] = node(v, w, pre[u]);pre[u] = cnt++;}int spfa(int n){queue<int> q;dis[0] = 0;book[0] = 1;q.push(0);int u, v, w;while(!q.empty()){u = q.front(); q.pop();for(int i = pre[u]; i != -1; i = mp[i].next){v = mp[i].v, w = mp[i].w;if(dis[v] > dis[u] + w){dis[v] = dis[u] + w;if(!book[v]){book[v] = 1;q.push(v);}}} book[u] = 0;}return dis[n + 1];}int U[MAXN], V[MAXN], W[MAXN];int pick[MAXN];int main(){int T, n, m, u, k;cin >> T;for(int kase = 1; kase <= T; kase++){scanf("%d %d", &n, &m);for(int i = 0; i < m; i++)scanf("%d %d %d", &U[i], &V[i], &W[i]);scanf("%d", &k);for(int i = 0; i < k; i++)scanf("%d", &pick[i]);int up = 1, ans = inf;while((1 << up) < n) up++;for(int i = 0; i <= up; i++){init(n);for(int j = 0; j < m; j++)addedge(U[j], V[j], W[j]);for(int j = 0; j < k; j++){u = pick[j];if(u & 1 << i) addedge(0, u, 0);else addedge(u, n + 1, 0);}ans = min(ans, spfa(n));init(n);for(int j = 0; j < m; j++)addedge(U[j], V[j], W[j]);for(int j = 0; j < k; j++){u = pick[j];if(u & 1 << i) addedge(u, n + 1, 0);else addedge(0, u, 0);}ans = min(ans, spfa(n));}printf("Case #%d: %d\n", kase, ans);} return 0;}


原创粉丝点击