zoukankan      html  css  js  c++  java
  • NOI2014 魔法森林 day1t2 SPFA

    这道题做法还是很多的,至少有人用最优性剪枝当场A掉了。我只有50分的暴力分(写丑了),SB我不会LCT,先写一下SPFA的神思路做法(说白了还是我SB),LCT以后定补。ORZ想出来的人(hq大神)。最近总感觉考试时没有发挥出全力,考完后一想才发现做法其实还是很好想的。

    题意:给一个节点n边m的图,每条边有两个权值a和b,要从1选择两个数x,y出发通过(a le x, b le y)的边走到n,求最小的x+y。

    想想What's SPFA?最短路?但是我们可以利用松弛操作找到特点两点间的边的最大值。用dis数组来保存从1点到当前点的路径上最大的b称为当前点花费b。做法的精妙之处在于:我们可以从小到大枚举x,之前能到达的点,现在仍然能到达,所以不用管x;如果SPFA时不清空dis数组,里面保存的就是在之前的较小的x的情况下能走到的点的花费b,现在有可能会通过走新边来减小b,新边就是权值恰好为a的边,每次取有这样的边的点进行SPFA即可。

    真是一道巧妙的题!

      1 //{HEADS
      2 #define FILE_IN_OUT
      3 #define debug
      4 #include <cstdio>
      5 #include <cstring>
      6 #include <cstdlib>
      7 #include <cmath>
      8 #include <ctime>
      9 #include <algorithm>
     10 #include <iostream>
     11 #include <fstream>
     12 #include <vector>
     13 #include <stack>
     14 #include <queue>
     15 #include <deque>
     16 #include <map>
     17 #include <set>
     18 #include <bitset>
     19 #include <complex>
     20 #include <string>
     21 #define REP(i, j) for (int i = 1; i <= j; ++i)
     22 #define REPI(i, j, k) for (int i = j; i <= k; ++i)
     23 #define REPD(i, j) for (int i = j; 0 < i; --i)
     24 #define STLR(i, con) for (int i = 0, sz = con.size(); i < sz; ++i)
     25 #define STLRD(i, con) for (int i = con.size() - 1; 0 <= i; --i)
     26 #define CLR(s) memset(s, 0, sizeof s)
     27 #define SET(s, v) memset(s, v, sizeof s)
     28 #define mp make_pair
     29 #define pb push_back
     30 #define PL(k, n) for (int i = 1; i <= n; ++i) { cout << k[i] << ' '; } cout << endl
     31 #define PS(k) STLR(i, k) { cout << k[i] << ' '; } cout << endl
     32 using namespace std;
     33 #ifdef debug
     34 #ifndef ONLINE_JUDGE
     35     const int OUT_PUT_DEBUG_INFO = 1;
     36 #endif
     37 #endif
     38 #ifdef ONLINE_JUDGE
     39     const int OUT_PUT_DEBUG_INFO = 0;
     40 #endif
     41 #define DG if(OUT_PUT_DEBUG_INFO)
     42 typedef long long LL;
     43 typedef double DB;
     44 typedef pair<int, int> i_pair;
     45 const int INF = 0x3f3f3f3f;
     46 //}
     47 
     48 const int maxn = 50000 + 10;
     49 const int maxm = 100000 + 10;
     50 const int maxe = maxm * 2;
     51 /*{ 前向星*/
     52 struct Edge {
     53     int edge;
     54     int head[maxn], to[maxe], next[maxe], la[maxe], lb[maxe];
     55     Edge() {
     56         edge = 0;
     57         memset(head, -1, sizeof head);
     58     }
     59     void addedge(int u, int v, int a, int b) {
     60         to[edge] = v;
     61         next[edge] = head[u];
     62         la[edge] = a;
     63         lb[edge] = b;
     64         head[u] = edge++;
     65     }
     66 }E;
     67 /*}*/
     68 int n, m;
     69 
     70 int dis[maxn];
     71 queue<int> Q;
     72 vector<int> p[maxn];
     73 bitset<maxn> vis;
     74 
     75 void spfa(int u, int a) {
     76     Q.push(u);
     77     vis.reset();
     78     vis[u] = 1;
     79     while(!Q.empty()) {
     80         int v = Q.front(); Q.pop();
     81         vis[v] = 0;
     82         for(int i = E.head[v]; i != -1; i = E.next[i]) {
     83             if(E.la[i] <= a && max(dis[v], E.lb[i]) < dis[E.to[i]]) {
     84                 dis[E.to[i]] = max(dis[v], E.lb[i]);
     85                 if(!vis[E.to[i]]) {
     86                     Q.push(E.to[i]);
     87                     vis[E.to[i]] = 1;
     88                 }
     89             }
     90         }
     91     }
     92 }
     93 
     94 int main() {
     95     //FILE_INIT("forest");
     96     freopen("forest.in", "r", stdin);
     97     freopen("forest.out", "w", stdout);
     98 
     99     scanf("%d%d", &n, &m);
    100     int Max = -INF;
    101     REP(i, m) {
    102         int u, v, a, b;
    103         scanf("%d%d%d%d", &u, &v, &a, &b);
    104         E.addedge(u, v, a, b);
    105         E.addedge(v, u, a, b);
    106         p[a].pb(u);
    107         p[a].pb(v);
    108         Max = max(Max, a);
    109     }
    110     int ans = INF;
    111     SET(dis, INF);
    112     dis[1] = 0;
    113     REP(i, Max) {
    114         STLR(j, p[i]) {
    115             spfa(p[i][j], i);
    116         }
    117         if(dis[n] != INF) {
    118             ans = min(ans, dis[n] + i);
    119         }
    120     }
    121     if(ans == INF) {
    122         printf("%d
    ", -1);
    123     } else {
    124         printf("%d
    ", ans);
    125     }
    126 
    127     return 0;
    128 }
    View Code
  • 相关阅读:
    flask基础之jijia2模板使用基础(二)
    python之微信公众号开发(基本配置和校验)
    flask插件系列之SQLAlchemy基础使用
    python基础之常用的高阶函数
    服务器部署之nginx的配置
    python之gunicorn的配置
    python内置模块之unittest测试(五)
    python之celery使用详解一
    git服务器的简单搭建
    python模块分析之logging日志(四)
  • 原文地址:https://www.cnblogs.com/hzf-sbit/p/3877739.html
Copyright © 2011-2022 走看看