zoukankan      html  css  js  c++  java
  • HDU 6166 Senior Pan

    HDU 6166 Senior Pan

    Problem Description

    Senior Pan fails in his discrete math exam again. So he asks Master ZKC to give him graph theory problems everyday.
    The task is simple : ZKC will give Pan a directed graph every time, and selects some nodes from that graph, you can calculate the minimum distance of every pair of nodes chosen in these nodes and now ZKC only cares about the minimum among them. That is still too hard for poor Pan, so he asks you for help.
    

    Input

    The first line contains one integer T, represents the number of Test Cases.1≤T≤5.Then T Test Cases, for each Test Cases, the first line contains two integers n,m representing the number of nodes and the number of edges.1≤n,m≤100000
    Then m lines follow. Each line contains three integers xi,yi representing an edge, and vi representing its length.1≤xi,yi≤n,1≤vi≤100000
    Then one line contains one integer K, the number of nodes that Master Dong selects out.1≤K≤n
    The following line contains K unique integers ai, the nodes that Master Dong selects out.1≤ai≤n,ai!=aj
    

    Output

    For every Test Case, output one integer: the answer
    

    Sample Input

    1
    5 6
    1 2 1
    2 3 3
    3 1 3
    2 5 1
    2 4 2
    4 3 1
    3
    1 3 5
    

    Sample Output

    Case #1: 2
    
    	一个图,然后指定几个点,问这些点之间所有组合的起点终点中最短的一条路径是什么。
    	多源多汇,比较容易想到建总源点和总汇点。之间跑源点汇点的最短路。但是这样问题很多。看来别人的操作后,随机把k个点分成两组。然后把两组分别连源点和汇点,权值0.一次最短路。如果答案的两个点被你分到了两个集合,那么答案就出来了。由于答案被分到两个集合的概率是0.5.做n次期望能有n/2次能获得答案。那么直接来个十几次随机。AC概率就很大了。
    	官方是按某个二进制位划分,因为来个数字不同,必有某位二进制是不同的。那么对二进制的每一位的0,1分集合就能包含所有划分集合。
    
    /**
    令人窒息的随机算法,通过多次随机获得较高的AC概率
    
    官方解法是,两个数字不同,那么肯定有一位二进制是不同的。
    
    所以可以通过枚举二进制位的仿佛枚举所有集合对
    
    */
    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAXN = 1e5 + 10;
    typedef long long LL;
    const LL INF = 0x3F3F3F3F3F3F3F3F;
    
    int n, m, k, first[MAXN], sign, arr[MAXN];
    
    struct Input {
        int u, v;
        LL w;
    } in[MAXN];
    
    struct Edge {
        int to, next;
        LL w;
    } edge[MAXN * 4];
    
    void init() {
        memset(first, -1, sizeof(first));
        sign = 0;
    }
    
    void add_edge(int u, int v, LL w) {
        edge[sign].to = v;
        edge[sign].w = w;
        edge[sign].next = first[u];
        first[u] = sign++;
    }
    
    LL dist[MAXN];
    
    int inq[MAXN];
    
    LL spfa(int s, int t) {
        memset(dist, 0x3F, sizeof(dist));
        memset(inq, 0, sizeof(inq));
        queue<int>que;
        que.push(s);
        inq[s] = 1;
        dist[s] = 0;
        while(!que.empty()) {
            int now = que.front();
            que.pop();
            inq[now] = 0;
            for(int i = first[now]; ~i; i = edge[i].next) {
                int to = edge[i].to;
                LL w = edge[i].w;
                if(dist[to] > dist[now] + w) {
                    dist[to] = dist[now] + w;
                    if(!inq[to]) {
                        inq[to] = 1;
                        que.push(to);
                    }
                }
            }
        }
        return dist[t];
    }
    
    LL random() {
        init();
        for(int i = 1; i <= m; i++ ) {
            int u = in[i].u, v = in[i].v, w = in[i].w;
            add_edge(u, v, w);
        }
        for(int i = 1; i <= k; i++ ) {
            int ac = rand() % 2;
            if(ac) {
                add_edge(0, arr[i], 0);
            } else {
                add_edge(arr[i], n + 1, 0);
            }
        }
        return spfa(0, n + 1);
    }
    
    int main()
    {
        int t;
        scanf("%d", &t);
        srand(unsigned(time(0)));
        for(int cas = 1; cas <= t; cas++ ) {
            scanf("%d %d", &n, &m);
            for(int i = 1; i <= m; i++ ) {
                int u, v, w;
                scanf("%d %d %d", &u, &v, &w);
                in[i].u = u, in[i].v = v, in[i].w = w;
            }
            scanf("%d", &k);
            for(int i = 1; i <= k; i++ ) {
                scanf("%d", &arr[i]);
            }
            int limit = 20;
            LL ans = INF;
            for(int cnt = 1; cnt <= limit; cnt++ ) {
                ans = min(ans, random());
            }
            printf("Case #%d: %lld
    ", cas, ans);
        }
    
        return 0;
    }
    
  • 相关阅读:
    高并发下缓存失效问题及解决方案
    行为型设计模式
    Redisson
    行为型设计模式
    Docker 安装 Elasticsearch 和 Kibana
    行为型设计模式
    C# 使用 WebBrowser 实现 HTML 转图片功能
    .NET 程序下锐浪报表 (Grid++ Report) 的绿色发布指南
    .NET 程序员的 Playground :LINQPad
    Windows 服务器上的 WordPress 站点优化笔记
  • 原文地址:https://www.cnblogs.com/Q1143316492/p/9293736.html
Copyright © 2011-2022 走看看