Chgtaxihe's blog Chgtaxihe's blog
首页
练习
算法学习
读书笔记
小玩意

Chgtaxihe

首页
练习
算法学习
读书笔记
小玩意
  • 训练补题
  • Codeforces 刷题计划
  • 概率dp练习
  • dp专题练习
  • 数论练习
  • 搜索专题练习
  • 图论练习
  • 基础字符串练习
  • AtCoder练习
  • 题解们
  • solutions

  • 训练补题

    • 训练补题-个人1
    • 训练补题-个人10
    • 训练补题-个人2
    • 训练补题-个人5
    • 训练补题-个人6
    • 训练补题-个人8
    • 训练补题-个人9
      • Wow! Such Sequence! (HDU 4893)
      • Caravans (URAL 2034)
        • AC代码(动态加点)--140ms
        • AC代码(记忆化搜索)--125ms
    • 训练补题-牛客训练赛1
    • 训练补题-牛客训练赛10
    • 训练补题-牛客训练赛2
    • 训练补题-牛客训练赛3
    • 训练补题-牛客训练赛6
    • 训练补题-牛客训练赛6
    • 训练补题-牛客训练赛7
    • 训练补题-牛客训练赛8
    • 训练补题-牛客训练赛9
    • 训练补题-杭电多校10
    • 训练补题-杭电多校2
    • 训练补题-杭电多校3
    • 训练补题-杭电多校6
    • 训练补题-杭电多校9
    • NWERC 2018-训练补题11
    • SpbKOSHP 19-训练补题12
    • Gym102576-训练补题13
    • GCPC2018-训练补题14
    • Gym102202-训练补题15

训练补题-个人9

# 个人排位赛9补题记录

# Wow! Such Sequence! (HDU 4893)

HDU的防火墙开的有点过分了,今天比赛的提交全部Network Failed。赛后发现是因为代码里有关键字update~

BTW,检查代码时发现pushdown操作下放lazy标记部分写错了:下放了lazy标记但是没有去更新子节点的值

# Caravans (URAL 2034)

必须要吐槽一下这个题面:一开始我理解为,求出所有商队的所有必经点ppp,求rrr到ppp的最小距离。

结果题目的意思是:强盗知道商队会怎么走,但只能从rrr出发,问所有走法中,距离最大为多少。因此,强盗不需要埋伏在必经点!

思路:先求出从sss到fff的最短路长度lll,再求从rrr到每一个点的距离dr[i]=dist(r,i)dr[i]=dist(r,i)dr[i]=dist(r,i)。建一张新图G′G'G′,每次从{x∉G′∣x∈G}\{x\not\in G'\mid x\in G\}{x∈G′∣x∈G}中选取一个dr[p]dr[p]dr[p]最大的点加入G′G'G′中,检查dG[f]dG[f]dG[f]是否为lll(dG[i]dG[i]dG[i]代表新图中,从sss出发到iii的最短路,若sss不在新图中,则dG[i]=infdG[i]=infdG[i]=inf),若是,则dr[p]dr[p]dr[p]为答案。

剩下唯一需要动点脑子的地方,就是加点以后如何计算dGdGdG,显然dijkstradijkstradijkstra即可。


其实上述思路可以再优化一下,二分搜索一个值midmidmid,令新图包含所有dr[x]≤middr[x]\le middr[x]≤mid的点xxx,再检测新图中dist(s,f)dist(s,f)dist(s,f)是否等于lll即可。

PS. 说实话,我看了下别人二分的做法,在105ms左右,实现的差的甚至要上170ms。因此这题的二分优化可有可无。


另外,本题有DP(但我更愿意称之为记忆化搜索)的解法,代码更短

定义dfs(u)dfs(u)dfs(u),返回强盗在uuu所在的最短路上拦截商队的最小代价,对所有满足dist[x]=dist[u]+1dist[x]=dist[u]+1dist[x]=dist[u]+1的点,dfs(u)=min(dr[u],max(dfs(x)))dfs(u)=min(dr[u], max(dfs(x)))dfs(u)=min(dr[u],max(dfs(x)))。特别的,dfs(s)=dr[s]dfs(s)=dr[s]dfs(s)=dr[s]

# AC代码(动态加点)--140ms

#include <bits/stdc++.h>
#define Android ios::sync_with_stdio(false), cin.tie(NULL)
using namespace std;

const int inf = 0x3f3f3f3f;
const int maxn = 3e5 + 100;

int n, m, s, f, r, opt;
int ds[maxn], dr[maxn], dG[maxn];
bool inG[maxn];
vector<int> G[maxn];

void bfs(int src, int * dist){
    memset(dist, 0x3f, sizeof ds);
    dist[src] = 0;
    queue<int> que;
    que.push(src);
    while(!que.empty()){
        int u = que.front(); que.pop();
        for(int v:G[u]) if(dist[v] > dist[u] + 1){
            dist[v] = dist[u] + 1;
            que.push(v);
        }
    }
}

void dijkstra(int nw_point){
    inG[nw_point] = true;
    if(nw_point != s){
        for(int v:G[nw_point]){
        if(inG[nw_point] && dG[nw_point] > dG[v] + 1) 
            dG[nw_point] = dG[v] + 1;
        }
    }else{
        dG[nw_point] = 0;
    }
    if(dG[nw_point] == inf) return;

    priority_queue<pii, vector<pii>, greater<pii> > que;
    que.push({dG[nw_point], nw_point});
    while(!que.empty()){
        pii pt = que.top(); que.pop();
        if(pt.first != dG[pt.second]) continue;

        for(int v:G[pt.second]){
            if(inG[v] && dG[v] > dG[pt.second] + 1){
                dG[v] = dG[pt.second] + 1;
                que.push({dG[v], v});
            }
        }
    }
}

void solve(){
    cin >> n >> m;
    for(int i=0, u, v; i<m; i++){
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    cin >> s >> f >> r;
    bfs(s, ds);
    opt = ds[f];
    bfs(r, dr);
    memset(dG, 0x3f, sizeof dG);

    vector<int> pts(n);
    for(int i=0; i<n; i++) pts[i] = i + 1;
    sort(pts.begin(), pts.end(), [&](int x, int y){
        return dr[x] > dr[y];
    });

    for(int i=0; i<n; i++){
        dijkstra(pts[i]);
        if(dG[f] == opt){
            cout << dr[pts[i]] << '\n';
            break;
        }
    }
}

signed main(){
    Android;
    solve();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

# AC代码(记忆化搜索)--125ms

#include <bits/stdc++.h>
#define Android ios::sync_with_stdio(false), cin.tie(NULL)
using namespace std;

const int inf = 0x3f3f3f3f;
const int maxn = 3e5 + 100;

int n, m, s, f, r;
int ds[maxn], dr[maxn];
vector<int> G[maxn];

void bfs(int src, int * dist){
    // 同动态加点
}

int dp[maxn];
int dfs(int u){
    if(dp[u] != -1) return dp[u];
    int ans = dr[u], par = (u==s)?inf:0;
    for(int v:G[u]){
        if(ds[v] == ds[u] - 1){
            par = max(par, dfs(v));
        }
    }
    return dp[u] = min(ans, par);
}

void solve(){
    memset(dp, -1, sizeof dp);
    cin >> n >> m;
    for(int i=0, u, v; i<m; i++){
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    cin >> s >> f >> r;
    bfs(s, ds);
    bfs(r, dr);
    cout << dfs(f) << '\n';  
} 

signed main(){
    Android;
    solve();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
上次更新: 2021/02/24, 03:37:30
训练补题-个人8
训练补题-牛客训练赛1

← 训练补题-个人8 训练补题-牛客训练赛1→

最近更新
01
深入理解Java虚拟机
03-04
02
DNS工作原理
02-27
03
改用VuePress啦
02-23
更多文章>
Theme by Vdoing | Copyright © 2019-2021
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式