zoukankan      html  css  js  c++  java
  • 校内训练0611 最近点对

    【题目大意】

    n个点m条边带权无向图,求前k个点之间的最短距离,多组数据。

    T<=10,n<=50000,k<=1000

    【题解】

    首先暴力O(Tknlogn)是过不了的。。。

    考虑比暴力优秀一点的做法?随机化!

    我们随机一半的点分在A,一半的点分在B,S向A中点连边,边权0;B中点想T连边,边权0.

    每次求S->T的最短路对应的就是A点集->B点集的最短路。

    多随机几次就行了。

    标程0.5s,标准时限1.5s

    本机标程2s,仿照开3倍时限,开到6s,过了。。

    复杂度O(T*nT*nlogn),nT为随机次数,我取了5,本机太慢了qwq

    # include <queue>
    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 4e5 + 10;
    const int mod = 1e9+7, INF = 1e9;
    
    # define RG register
    # define ST static
    
    int n, m, K, S, T, id[M], old[M];
    int head[M], nxt[M], to[M], w[M], tot=0;
    inline void add(int u, int v, int _w) {
         ++tot; nxt[tot] = head[u]; head[u] = tot;
        to[tot] = v; w[tot] = _w;
    }
    inline void adde(int u, int v, int _w) {
        add(u, v, _w); add(v, u, _w);
    }
    
    struct pa {
        int x, dis;
        pa() {}
        pa(int x, int dis) : x(x), dis(dis) {}
        friend bool operator < (pa a, pa b) {
            return a.dis > b.dis;
        }
    };
    
    int d[M]; 
    bool vis[M]; 
    priority_queue< pa > q;
    
    inline int dijkstra() {
        for (int i=1; i<=T; ++i) d[i] = INF, vis[i] = 0; 
        q.push(pa(S, 0)); d[S] = 0;
        while(!q.empty()) {
            pa t = q.top(); q.pop();
            if(vis[t.x]) continue;
            vis[t.x] = 1; 
            for (int i=head[t.x]; i; i=nxt[i]) {
                if(d[to[i]] > d[t.x] + w[i]) {
                    d[to[i]] = d[t.x] + w[i];
                    q.push(pa(to[i], d[to[i]]));
                }
            }
        }
        return d[T];
    }
    
    inline void sol() {
        cin >> n >> m >> K;
        for (int i=1, u, v, _w; i<=m; ++i) { 
            scanf("%d%d%d", &u, &v, &_w);
            adde(u, v, _w); 
        }
        for (int i=1; i<=K; ++i) id[i] = i; 
        for (int i=1; i<=K; ++i) old[i] = head[i]; 
        int nTOT = tot; S = n+1, T = n+2;
        int ans = INF;
        for (int Test=1; Test<=5; ++Test) {
            random_shuffle(id+1, id+K+1);
            for (int i=1; i<=K/2; ++i) adde(S, id[i], 0);
            for (int i=K/2+1; i<=K; ++i) adde(id[i], T, 0);
            ans = min(ans, dijkstra()); 
            for (int i=1; i<=K; ++i) head[i] = old[i];
            tot = nTOT; head[S] = head[T] = 0; 
        }
        cout << ans << endl; 
        tot = 0;
        for (int i=1; i<=n+2; ++i) head[i] = 0; 
    }
    
    int main() {
        freopen("nearest.in", "r", stdin);
        freopen("nearest.out", "w", stdout); 
        int T; cin >> T;
        while(T--) sol();
        return 0;
    }
    View Code
  • 相关阅读:
    python列表转json树菜单
    lvm分区创建和扩容
    分布式网络概述
    mycat权威指南阅读笔记--序言1
    Mongodb副本集实现及读写分离
    线程和进程
    socket客户端怎么判断http响应数据的结束
    java遍历http请求request的所有参数实现方法
    Java中mongodb使用and和or的复合查询
    idea @Override is not allowed when implementing interface method
  • 原文地址:https://www.cnblogs.com/galaxies/p/20170611_a.html
Copyright © 2011-2022 走看看