这道题做法还是很多的,至少有人用最优性剪枝当场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即可。

真是一道巧妙的题!

 //{HEADS
#define FILE_IN_OUT
#define debug
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <complex>
#include <string>
#define REP(i, j) for (int i = 1; i <= j; ++i)
#define REPI(i, j, k) for (int i = j; i <= k; ++i)
#define REPD(i, j) for (int i = j; 0 < i; --i)
#define STLR(i, con) for (int i = 0, sz = con.size(); i < sz; ++i)
#define STLRD(i, con) for (int i = con.size() - 1; 0 <= i; --i)
#define CLR(s) memset(s, 0, sizeof s)
#define SET(s, v) memset(s, v, sizeof s)
#define mp make_pair
#define pb push_back
#define PL(k, n) for (int i = 1; i <= n; ++i) { cout << k[i] << ' '; } cout << endl
#define PS(k) STLR(i, k) { cout << k[i] << ' '; } cout << endl
using namespace std;
#ifdef debug
#ifndef ONLINE_JUDGE
const int OUT_PUT_DEBUG_INFO = ;
#endif
#endif
#ifdef ONLINE_JUDGE
const int OUT_PUT_DEBUG_INFO = ;
#endif
#define DG if(OUT_PUT_DEBUG_INFO)
typedef long long LL;
typedef double DB;
typedef pair<int, int> i_pair;
const int INF = 0x3f3f3f3f;
//} const int maxn = + ;
const int maxm = + ;
const int maxe = maxm * ;
/*{ 前向星*/
struct Edge {
int edge;
int head[maxn], to[maxe], next[maxe], la[maxe], lb[maxe];
Edge() {
edge = ;
memset(head, -, sizeof head);
}
void addedge(int u, int v, int a, int b) {
to[edge] = v;
next[edge] = head[u];
la[edge] = a;
lb[edge] = b;
head[u] = edge++;
}
}E;
/*}*/
int n, m; int dis[maxn];
queue<int> Q;
vector<int> p[maxn];
bitset<maxn> vis; void spfa(int u, int a) {
Q.push(u);
vis.reset();
vis[u] = ;
while(!Q.empty()) {
int v = Q.front(); Q.pop();
vis[v] = ;
for(int i = E.head[v]; i != -; i = E.next[i]) {
if(E.la[i] <= a && max(dis[v], E.lb[i]) < dis[E.to[i]]) {
dis[E.to[i]] = max(dis[v], E.lb[i]);
if(!vis[E.to[i]]) {
Q.push(E.to[i]);
vis[E.to[i]] = ;
}
}
}
}
} int main() {
//FILE_INIT("forest");
freopen("forest.in", "r", stdin);
freopen("forest.out", "w", stdout); scanf("%d%d", &n, &m);
int Max = -INF;
REP(i, m) {
int u, v, a, b;
scanf("%d%d%d%d", &u, &v, &a, &b);
E.addedge(u, v, a, b);
E.addedge(v, u, a, b);
p[a].pb(u);
p[a].pb(v);
Max = max(Max, a);
}
int ans = INF;
SET(dis, INF);
dis[] = ;
REP(i, Max) {
STLR(j, p[i]) {
spfa(p[i][j], i);
}
if(dis[n] != INF) {
ans = min(ans, dis[n] + i);
}
}
if(ans == INF) {
printf("%d\n", -);
} else {
printf("%d\n", ans);
} return ;
}

NOI2014 魔法森林 day1t2 SPFA的更多相关文章

  1. BZOJ3669 [Noi2014]魔法森林(SPFA+动态加边)

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  2. bzoj 3669: [Noi2014]魔法森林 -- 动点spfa

    3669: [Noi2014]魔法森林 Time Limit: 30 Sec  Memory Limit: 512 MB 动点spfa Description 为了得到书法大家的真传,小E同学下定决心 ...

  3. 【BZOJ 3669】 3669: [Noi2014]魔法森林 (动态spfa)

    3669: [Noi2014]魔法森林 Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N ...

  4. NOI2014 魔法森林

    3669: [Noi2014]魔法森林 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 106  Solved: 62[Submit][Status] ...

  5. bzoj 3669: [Noi2014]魔法森林

    bzoj 3669: [Noi2014]魔法森林 Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号 ...

  6. 洛谷 P2387 [NOI2014]魔法森林 解题报告

    P2387 [NOI2014]魔法森林 题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2 ...

  7. bzoj 3669: [Noi2014]魔法森林 动态树

    3669: [Noi2014]魔法森林 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 363  Solved: 202[Submit][Status] ...

  8. BZOJ 3669: [Noi2014]魔法森林( LCT )

    排序搞掉一维, 然后就用LCT维护加边MST. O(NlogN) ------------------------------------------------------------------- ...

  9. BZOJ_3669_[Noi2014]魔法森林_LCT

    BZOJ_3669_[Noi2014]魔法森林_LCT Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节 ...

随机推荐

  1. redis中如何对 key 进行分类

    因为redis中的 hash是不支持设置过期时间的,如果我们要 设置过期时间,还要分类存储,可以用下面折中的方法 其实就是我们把 key 定义的有规律一些,通过在key的字符串内部 分类,上图只是因为 ...

  2. 访问修饰符public,private,protected和default的区别?

    类的成员不写访问修饰符默认为default,默认对于同一个包的其他类相当于公开(public),对于不是同一个包的其他类相当于私有(private). 受保护(protected)对子类相当于公开,对 ...

  3. springMVC新理解

    springmvc 中@Controller和@RestController的区别 1. Controller, RestController的共同点 都是用来表示spring某个类的是否可以接收HT ...

  4. 转ajax的jsonp的文章

    转:http://justcoding.iteye.com/blog/1366102/ Js是不能跨域请求.出于安全考虑,js设计时不可以跨域. 什么是跨域: 1.域名不同时. 2.域名相同,端口不同 ...

  5. ACM1258邻接表

    教训:使用邻接表的时候一定要把邻接表的结构组定义的足够大,不能仅仅等于节点的个数,因为线段的数量往往远超过节点的数量. 这个题目是拓扑排序练习,提高下理解. #include<iostream& ...

  6. HDU3231拓扑排序

    Box Relations Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  7. 中频IF

    Intermediate 频率是指中频. 一般RF射频有三个频率,基带频率,中频,射频. 射频是发射到空中的频率,也就是我们一般说的2.4G, Sub-1G.但这个频率太高,不利于放大器做增益控制.所 ...

  8. zTab layui多标签页组件

    zTab zTab是一个layui多标签页插件,仿照了layuiAdmin的iframe版Tab实现 当前版本v1.0 码云地址:https://gitee.com/sushengbuyu/zTab ...

  9. C11工具类:时间处理

    C++11提供时间管理类,包括三种类型:时间间隔duration,时钟clocks,时间点time point. 1.记录时常的duration 1.1 原型 duration表示一段时间间隔,用来记 ...

  10. PowerDesigner16连接mysql5.6逆向生成PDM

    一:首先安装ODBC驱动  https://dev.mysql.com/downloads/connector/odbc/  ,安装32位驱动 二:然后配置好ODBC数据源,控制面板\系统和安全\管理 ...