zoukankan      html  css  js  c++  java
  • ACM学习历程—HDU5521 Meeting(图论)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5521

    学习菊苣的博客,只粘链接,不粘题目描述了。

    题目大意就是一个人从1开始走,一个人从n开始走。让最后相遇的时间最短。

    题目就是个最短路,不过唯一不同的是,题目图的描述方式比较特别。

    从规模上来看,想把这张图描述成邻接矩阵或者邻接表是不可能的。

    必然只能按照题目要求的意思来存。

    于是第一步存图的方式,我采用了两个vector数组,(当然此处可以使用链式前向星),一个存了和点相关的集合有哪些in[],即这个点包含在哪些集合里面;一个存了集合里面有哪些点edge[]

    然后就是跑两遍最短路了,这里我采用了优先队列的spfa(貌似就是优先队列的dijikstra)。

    不过直接这样上去T了好多发。

    然后考虑到用了优先队列后,相当于优化了这个dp的过程,让每个点只需要遍历一次。那么,自然而然的,如果i遍历了集合s里面的所有点,自然集合s也只需要遍历一次。加了这一个剪枝就能AC了。由于遍历集合的时候,不是按照从最小权值集合开始的,所以这里没有对队列里面的元素进行判重,不过影响不是很大。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <set>
    #include <queue>
    #include <vector>
    #define LL long long
    
    using namespace std;
    
    struct node
    {
        int id, val;
        bool operator<(const node x) const
        {
            return val>x.val;
        }
    };
    const int maxN = 100005;
    const int maxM = 1000005;
    int n, m;
    vector<int> in[maxN];
    int dis[maxM];
    vector<int> edge[maxM];
    LL p[2][maxN];
    bool vis[maxM];
    
    void input()
    {
        scanf("%d%d", &n, &m);
        int t, s, k;
        for (int i = 0; i < m; ++i)
        {
            scanf("%d%d", &t, &s);
            dis[i] = t;
            for (int j = 0; j < s; ++j)
            {
                scanf("%d", &k);
                in[k].push_back(i);
                edge[i].push_back(k);
            }
        }
        memset(p, -1, sizeof(p));
    }
    
    void spfa(int from, int x)
    {
        memset(vis, false, sizeof(vis));
        priority_queue<node> q;
        node k, t;
        int w, u, v;
        k.id = from;
        k.val = 0;
        q.push(k);
        p[x][from] = 0;
        while (!q.empty())
        {
            k = q.top();
            q.pop();
            u = k.id;
            for (int i = 0; i < in[u].size(); ++i)
            {
                w = in[u][i];
                if (vis[w]) continue;
                for (int j = 0; j < edge[w].size(); ++j)
                {
                    v = edge[w][j];
                    if (u == v) continue;
                    if (p[x][v] == -1 || p[x][v] > p[x][u]+dis[w])
                    {
                        p[x][v] = p[x][u]+dis[w];
                        t.id = v;
                        t.val = p[x][v];
                        q.push(t);
                    }
                }
                vis[w] = true;
            }
        }
    }
    
    LL myMin(LL x, LL y)
    {
        if (x == -1) return y;
        else return min(x, y);
    }
    
    void work()
    {
        spfa(1, 0);
        spfa(n, 1);
        LL mi = -1;
        for (int i = 1; i <= n; ++i)
            if (p[0][i] != -1 && p[1][i] != -1)
                mi = myMin(mi, max(p[0][i], p[1][i]));
        if (mi == -1)
        {
            printf("Evil John
    ");
            return;
        }
        printf("%d
    ", mi);
        bool flag = false;
        for (int i = 1; i <= n; ++i)
            if (p[0][i] != -1 && p[1][i] != -1 && mi == max(p[0][i], p[1][i]))
            {
                if (flag) printf(" ");
                printf("%d", i);
                flag = true;
            }
        printf("
    ");
    }
    
    void clss()
    {
        for (int i = 0; i < m; ++i)
            edge[i].clear();
        for (int i = 1; i <= n; ++i)
            in[i].clear();
    }
    
    int main()
    {
        //freopen("test.in", "r", stdin);
        int T;
        scanf("%d", &T);
        for (int times = 0; times < T; ++times)
        {
            printf("Case #%d: ", times+1);
            input();
            work();
            clss();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    java解析xml实例——获取天气信息
    Wordpress可以用来做什么?
    Unity3D 快捷键
    Unity3D 快捷键
    OAuth和OpenID的区别
    OAuth和OpenID的区别
    PHP中require和include的区别
    PHP中require和include的区别
    iOS检测QQ是否安装
    iOS检测QQ是否安装
  • 原文地址:https://www.cnblogs.com/andyqsmart/p/4946016.html
Copyright © 2011-2022 走看看