zoukankan      html  css  js  c++  java
  • 【刷题】【最短路】【k点中最小两点间距离】Senior Pan

    题意:n个点,m条有向边,指定k个点,问你其中最近的两点距离为多少

    思路:这题的思路很巧妙,如果我们直接枚举两点做最短路那就要做C(k,2)次。

    但是我们换个思路,我们把k个点按照二进制每一位的0和1分类logn次,然后做集合最短距离。

    因为任意两个不等的数,总有一位不一样,所以每个点都有机会和其他点在不同集合。

    那么这样就花了logn次枚举了所有情况。集合最短距离可以指定一个超级源点和超级汇点,然后做两点最短路。

    (原文地址:https://www.cnblogs.com/KirinSB/p/10679711.html)
    #include<cmath>
    #include<set>
    #include<queue>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include <iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int maxn = 100000 + 10;
    const ull seed = 131;
    const int INF = 0x3f3f3f3f;
    const int MOD = 1000000007;
    struct Edge
    {
        int to, w, next;
    } edge[maxn * 2];
    struct node
    {
        int v, w;
        node(int _v = 0, int _w = 0): v(_v), w(_w) {}
        bool operator < (const node r) const
        {
            return w > r.w;
        }
    };
    int head[maxn], tot;
    void addEdge(int u, int v, int w)
    {
        edge[tot].w = w;
        edge[tot].to = v;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    int n, m, k;
    int dis[maxn], q[maxn];
    bool vis[maxn];
    int dij(int s, int e)
    {
        memset(vis, false, sizeof(vis));
        memset(dis, INF, sizeof(dis));
        priority_queue<node> Q;
        while(!Q.empty()) Q.pop();
        dis[s] = 0;
        Q.push(node(s, 0));
        node tmp;
        while(!Q.empty())
        {
            tmp = Q.top();
            Q.pop();
            int u = tmp.v;
            if(vis[u]) continue;
            vis[u] = true;
            for(int i = head[u]; i != -1; i = edge[i].next)
            {
                int v = edge[i].to;
                if(!vis[v] && dis[v] > dis[u] + edge[i].w)
                {
                    dis[v] = dis[u] + edge[i].w;
                    Q.push(node(v, dis[v]));
                }
            }
        }
        return dis[e];
    }
    void init()
    {
        memset(head, -1, sizeof(head));
        tot = 0;
    }
    int a[maxn], b[maxn], w[maxn];
    int main()
    {
        int T, ca = 1;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= m; i++)
            {
                scanf("%d%d%d", &a[i], &b[i], &w[i]);
            }
            scanf("%d", &k);
            for(int i = 1; i <= k; i++)
            {
                scanf("%d", &q[i]);
            }
            int ans = INF, p = 0;
            while(n >> p)
            {
                init();
                for(int i = 1; i <= m; i++)
                    addEdge(a[i], b[i], w[i]);
                for(int i = 1; i <= k; i++)
                    if((q[i] >> p) & 1)
                        addEdge(0, q[i], 0);
                    else
                        addEdge(q[i], n + 1, 0);
                ans = min(ans, dij(0, n + 1));
                init();
                for(int i = 1; i <= m; i++)
                    addEdge(a[i], b[i], w[i]);
                for(int i = 1; i <= k; i++)
                {
                    if((q[i] >> p) & 1)
                        addEdge(q[i], 0, 0);
                    else
                        addEdge(n + 1, q[i], 0);
                }
                ans = min(ans, dij(n + 1, 0));
                p++;
            }
            printf("Case #%d: %d
    ", ca++, ans);
        }
        return 0;
    }
     
  • 相关阅读:
    UIButtonIOS开发
    SharePoint Server 2007 SP1 已发布
    SharePoint 2007 External Binary Storage Component Preview 发布
    WSS 3.0 & MOSS 2007 SDK 1.1
    SharePoint工作流(ASP.NET表单版)教学视频
    Finally...
    Windows SharePoint Services 3.0 "Visual How Tos" 视频系列
    SharePoint 补丁
    在SharePoint Workflow中使用InfoPath Form的几个Tips
    对于Office Open XML文档格式,请发表您的看法
  • 原文地址:https://www.cnblogs.com/xwww666666/p/11820227.html
Copyright © 2011-2022 走看看