fjutacm 3700 这是一道数论题 : dijkstra O(mlogn) 二进制分类 O(k) 总复杂度 O(k * m * logn)
1 /** 2 problem: http://www.fjutacm.com/Problem.jsp?pid=3700 3 按二进制将k个待查点分类分别跑dijkstra 4 **/ 5 #include<stdio.h> 6 #include<vector> 7 #include<queue> 8 using namespace std; 9 10 const int MAXN = 505; 11 const int MAXM = 3e4+5; 12 const int INF = 0x3f3f3f3f; 13 14 int ans; 15 16 template <typename T> 17 class Graphics { 18 private: 19 struct Edge { 20 int to, next; 21 T w; 22 } edge[MAXM]; 23 int first[MAXN], sign; 24 int sumOfPoint; 25 struct Node{ 26 int to; 27 T w; 28 Node(int a, int b):to(a), w(b){} 29 Node(){} 30 bool friend operator < (const Node &a, const Node &b){ 31 return a.w > b.w; 32 } 33 }; 34 public: 35 void clear(int n) { 36 sumOfPoint = n; 37 for(int i = 1; i <= n; i ++) { 38 first[i] = -1; 39 } 40 sign = 0; 41 } 42 void addEdgeOneWay(int u, int v, int w) { 43 edge[sign].to = v; 44 edge[sign].w = w; 45 edge[sign].next = first[u]; 46 first[u] = sign ++; 47 } 48 void addEdgeTwoWay(int u, int v, int w) { 49 addEdgeOneWay(u, v, w); 50 addEdgeOneWay(v, u, w); 51 } 52 vector<T> dijkstra(const vector<int> &start) { 53 vector<T> dist(sumOfPoint+1, INF); 54 vector<bool> visit(sumOfPoint+1); 55 priority_queue<Node> bfs; 56 for(unsigned i = 0; i < start.size(); i ++) { 57 bfs.push(Node(start[i], 0)); 58 } 59 while(!bfs.empty()) { 60 Node now = bfs.top(); 61 bfs.pop(); 62 if(visit[now.to]) { 63 continue; 64 } 65 visit[now.to] = true; 66 dist[now.to] = now.w; 67 for(int i = first[now.to]; i != -1; i = edge[i].next) { 68 int to = edge[i].to, w = edge[i].w; 69 if(now.w + w > ans) continue; /// 剪枝 当最短路已经大于当前最优值也不用继续找了 70 if(!visit[to]) { 71 bfs.push(Node(to, now.w + w)); 72 } 73 } 74 } 75 return dist; 76 } 77 }; 78 79 class Solution { 80 private: 81 int n, m, u, v, w, k; 82 int kk[MAXN]; 83 Graphics<int> graph; 84 public: 85 void solve() { 86 int t; 87 scanf("%d", &t); 88 while(t --) { 89 scanf("%d%d", &n, &m); 90 graph.clear(n); 91 while(m --) { 92 scanf("%d%d%d", &u, &v, &w); 93 graph.addEdgeOneWay(u, v, w); 94 } 95 scanf("%d", &k); 96 for(int i = 0; i < k; i ++) { 97 scanf("%d", &kk[i]); 98 } 99 ans = INF; 100 for(int i = 0; i < 10; i ++) { 101 vector<int> first, second; 102 for(int j = 0; j < k; j ++) { 103 if(kk[j] >> i & 1) { 104 first.push_back(kk[j]); 105 } else { 106 second.push_back(kk[j]); 107 } 108 } 109 vector<int> cur = graph.dijkstra(first); 110 for(unsigned j = 0; j < second.size(); j ++) { 111 ans = min(ans, cur[second[j]]); 112 } 113 cur = graph.dijkstra(second); 114 for(unsigned j = 0; j < first.size(); j ++){ 115 ans = min(ans, cur[first[j]]); 116 } 117 } 118 printf("%d\n", ans); 119 } 120 } 121 } DarkScoCu; 122 123 int main() { 124 DarkScoCu.solve(); 125 return 0; 126 }