zoukankan      html  css  js  c++  java
  • spfa+剪枝 或者 dij+手写堆+剪枝 UOJ 111

    http://uoj.ac/problem/111

    好像NOIP里面的题目...有好多都是...能通过xjbg剪枝来...AC题目的?

    得好好学一下这些剪枝黑科技了...

    思路:我觉得这位大佬说的很完善了:http://blog.csdn.net/herano/article/details/58639052

    竟然能卡分块暴力...hack数据不良心...不过好像最坏情况的边实在是太多了,没办法改变MLE的结局...?(其实3000000还好吧?)

    然后就是xjbg优化了,对每一个块删除重复跑的。对于step<=sqrt(n)的,我们如果找到了下一个块中存在step相同的,我们就不用再找了,好像就是这样= =。

    然后spfa跑一波即可(竟然卡了dijstra,难道要手写堆吗?

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <bits/stdc++.h>
    using namespace std;
    #pragma comment(linker,"/STACK:102400000,102400000")
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define haha printf("haha
    ")
    const int maxn = 30000 + 5;
    int n, m;
    int d[maxn];
    vector<int> G[maxn];
    bool have[maxn][200 + 5];
    int s, t;
    bool vis[maxn];
    
    int solve(){
        queue<int> que;
        memset(d, 0x7f, sizeof(d));
        d[s] = 0;
        que.push(s);
        while (!que.empty()){
            int u = que.front();
            que.pop();
            vis[u] = false;
            for (int i = 0; i < G[u].size(); i++){
                int step = G[u][i];
                for (int j = 1; u + step * j < n; j++){
                    int v = u + step * j;
                    if (d[v] > d[u] + j){
                        d[v] = d[u] + j;
                        if (!vis[v]){
                            que.push(v);
                            vis[v] = true;
                        }
                    }
                    if (step <= 200 && have[v][step]) break;
                }
                for (int j = 1; u - step * j >= 0; j++){
                    int v = u - step * j;
                    if (d[v] > d[u] + j){
                        d[v] = d[u] + j;
                        if (!vis[v]){
                            que.push(v);
                            vis[v] = true;
                        }
                    }
                    if (step <= 200 && have[v][step]) break;
                }
            }
        }
        return d[t] == 0x7f7f7f7f ? -1 : d[t];
    }
    
    int main(){
        cin >> n >> m;
        for (int i = 0; i < m; i++){
            int a, b; scanf("%d%d", &a, &b);
            if (i == 0) s = a;
            if (i == 1) t = a;
            G[a].pb(b);
            if (b <= 200) have[a][b] = 1;
        }
        for (int i = 0; i < n; i++){
            sort(ALL(G[i]));
            G[i].erase(unique(ALL(G[i])), G[i].end());
        }
        printf("%d
    ", solve());
        return 0;
    }
    View Code
  • 相关阅读:
    UML中类图的符号解释
    Vim简明教程【CoolShell】
    C++ 指针—02 指针与引用的对照
    一个通用onReady函数的实现
    内存泄漏以及常见的解决方法
    个人博客之路
    WPF 设置WebBrowser控件不弹脚本错误提示框
    Solr使用入门指南
    用C语言写解释器(一)——我们的目标
    数据库索引的作用和长处缺点
  • 原文地址:https://www.cnblogs.com/heimao5027/p/6669326.html
Copyright © 2011-2022 走看看