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 }

 

posted @ 2019-04-12 22:53  DarkScoCu  阅读(249)  评论(0编辑  收藏  举报