Personal template (for 2021 ICPC Jinan Station version)

preface

  1. [November 13, 2021] icpc Jinan Station will deal with it first.

Black Technology

Default source

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int mod = 1e9 + 7;
//Read quickly
void read(int &x) {
    int res = 0, f = 1;
    char c = getchar();
    while (!isdigit(c)) {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (isdigit(c)) res = (res << 1) + (res << 3) + (c - '0'), c = getchar();
    x = res * f;
}
//Lose
void OUT(int x) {
    if (x < 0) x = -x, putchar('-');
    if (x > 9) OUT(x / 10);
    putchar(x % 10 + '0');
}
void print(int a, char c) { OUT(a), putchar(c); }
//Inverse element
int Inv(int x) { return (x == 1) ? x : (x - x / mod) * Inv(x % mod) % mod; }
//Combination number
struct Comb {
    /*You still have to learn to knock yourself*/
    int re[N], inv[N], fac[N];
    void init(int n) {
        fac[0] = fac[1] = 1;
        inv[1] = 1;  //No inv[0]
        re[0] = re[1] = 1;
        for (int i = 2; i <= n; i++) {
            fac[i] = fac[i - 1] * i % mod;
            inv[i] = (mod - mod / i) * inv[mod % i] % mod;
            re[i] = re[i - 1] * inv[i] % mod;
        }
    }
    int C(int a, int b) { return fac[a] * re[b] % mod * re[a - b] % mod; }
};

signed main() {}
/*

*/

The art of violence

bitset

Usage collection

/*Header file*/
#include<bitset>

/*Specify size*/
bitset<1000> bs; //a bitset with 1000 bits

/*Constructor*/
bitset(): Everyone is false
bitset(unsigned long val): Set as val Binary form of
bitset(const string& str): Set to 01 string str

/*operator*/
operator []: Access a specific bit
operator ==/!=: Compare two bitset Whether the content is exactly the same.
operator &/&=/|/|=/^/^=/~: Bitwise AND/or/XOR/Reverse operation. bitset Only with bitset Perform bit operations. To perform bit operations with integers,
First convert the shape to bitset. 
operator <</>>/<<=/>>=: Shift binary left/Shift right
operator <</>>: Stream operator, which means you can cin/cout Input and output.

/*Member function*/
count(): return true Number of
size(): return bitset The size of the.
test(pos): It and vector Medium at()The role of is the same, and[]The difference between operators is out of bounds checking.
any(): If there is a yes true Then return true,Otherwise return false. 
none(): If all bits are false Then return true,Otherwise return false. 
all(): C++11,If all bits are true Then return false,Otherwise return false. 

set(): Will the whole bitset Set as true. 
set(pos,val=true): Set a bit to true/false. 
reset(): Will the whole bitset Set as false. 
reset(pos): Set a bit to false. amount to set(pos,false). 
flip(): Flip each bit. (0<->1,Equivalent to an XOR that is all 1 bitset)
flip(pos): Flip a bit.

to_string(): Returns the converted String representation.
to_ulong(): Returns the converted unsigned long Express( long stay NT And 32 bits POSIX System down and int Same, in
64 position POSIX Lower and long long Same).
to_ullong(): C++11,Returns the converted unsigned long long expression.

/*Write a member function that is not in the document*/
_Find_first(): return bitset first true Subscript, if not true Then return bitset The size of the.
_Find_next(pos): return pos Trailing (subscript) is strictly greater than pos First true Subscript, if pos Not back true Then return bitset The size of the.

Application example (combined with emerald sieve)

bitset<N> vis;
void Prime(int n){
    vis.set();
    vis[0]=vis[1]=0;
    for(int i=2;i*i<=n;i++){
        if(vis[i]){
            for(int j=i+i;j<=n;j+=i) vis[j]=0;
        }
    }
}

vector

v.front();
v.back();

graph theory

shortest path

dijkstra

/*
1.Title Link: [p4779 [template] single source shortest path (Standard Version)]( https://www.luogu.com.cn/problem/P4779)
	a.Note that there is a directed edge 
*/
#include <bits/stdc++.h>
#define read(x) scanf("%d", &x)
#define print(a, c) printf("%d%c", a, c)
#define pb push_back
 
using namespace std;
const int maxn = 2e5 + 10;
const int inf = 2e9;
 
struct node {
    int to, w;
    node() {}
    node(int _to, int _w) { to = _to, w = _w; }
};
struct pii {
    int fi, se;
    pii() {}
    pii(int _fi, int _se) { fi = _fi, se = _se; }
    bool operator<(pii b) const { return fi > b.fi; }
};
priority_queue<pii> q;
int n, m, s;
int u, v, w;
vector<node> g[maxn];
int dis[maxn], vis[maxn];
void dijkstra(int s) {
    for (int i = 1; i <= n; i++) dis[i] = inf, vis[i] = 0;
    dis[s] = 0;
    q.push(pii(0, s));
    while (!q.empty()) {
        pii now = q.top();
        q.pop();
        int d = now.fi, i = now.se;  //Distance and subscript
        if (vis[i])
            continue;  //It is normal that the previously marked points are still not taken out in the priority queue. They will be taken out at that time
        vis[i] = 1;
        for (auto j : g[i]) {
            if (vis[j.to]) continue;
            //Slack operation
            if (d + j.w < dis[j.to]) {
                dis[j.to] = d + j.w;
                q.push(pii(dis[j.to], j.to));
            }
        }
    }
}
signed main() {
    read(n), read(m), read(s);
    for (int i = 1; i <= m; i++) {
        read(u), read(v), read(w);
        g[u].pb(node(v, w));
    }
    dijkstra(s);
    for (int i = 1; i <= n; i++) print(dis[i], ' ');
    return 0;
}

SPFA (when it is put into the queue, vis[s]=1, and when it is taken out, vis[now]=0, update all that can be updated, and when it is updated, put all that can be put in, that is, x with vis[x]=0)

/*
1.Title Link: (and the previous title)
*/
#include <bits/stdc++.h>
#define read(x) scanf("%d", &x)
#define print(a, c) printf("%d%c", a, c)
#define pb push_back
 
using namespace std;
const int maxn = 2e5 + 10;
const int inf = 2e9;
 
struct node {
    int to, w;
    node() {}
    node(int _to, int _w) { to = _to, w = _w; }
};
int n, m, s;
int u, v, w;
vector<node> g[maxn];
int dis[maxn], vis[maxn];
void spfa() {
    for (int i = 1; i <= n; i++) dis[i] = inf, vis[i] = 0;
    dis[s] = 0;
    queue<int> q;
    q.push(s), vis[s] = 1;
    while (!q.empty()) {
        int x = q.front();
        q.pop(), vis[x] = 0;  //After all, there is generally no self ring
        for (auto i : g[x]) {
            /* if
             * (vis[i.to])continue;No, it doesn't mean that the algorithm can't be optimized in the queue! - it should be placed below!*/
            if (dis[x] + i.w < dis[i.to]) {
                dis[i.to] = dis[x] + i.w;
                if (!vis[i.to]) q.push(i.to), vis[i.to] = 1;
            }
        }
    }
}
signed main() {
    read(n), read(m), read(s);
    for (int i = 1; i <= m; i++) {
        read(u), read(v), read(w);
        g[u].pb(node(v, w));
    }
    spfa();
    for (int i = 1; i <= n; i++) print(dis[i], ' ');
    return 0;
}

Floyd

for (int k = 1; k <= n; k++)
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) g[i][j] = min(g[i][j], g[i][k] + g[k][j]);

Shortest path tree (application)

  1. Concept: a tree formed by the shortest path (just a concept, expansion is not very strong).

Shortest path tree count

  1. Title Link: Dark Castle LibreOJ - 10064
  2. Meaning: n ( 1 ≤ n ≤ 1000 ) n(1\le n\le 1000) n(1 ≤ n ≤ 1000) points, m undirected edges, and the length of each edge is l i ( 1 ≤ l ≤ 200 ) l_i(1\le l\le200) li (1 ≤ l ≤ 200), find the number of different shortest path trees (starting from 1) (result pair) 2 31 − 1 2^{31}-1 231 − 1).
  3. Problem solution: find the number of the previous node of each point (meet the short circuit, i.e. dis[u]+w==dis[v], dis[i] represents the shortest distance from node s to I), and finally multiply and subtract.
  4. Operation: operate during relaxation operation (the second operation is recommended for spfa, and the first one has more or less problems!) or operate after finding the shortest circuit of all points.

Template (shortest path count):

/*
1.The title is "Dark Castle" above
*/
/*Operation 1: modify the relaxation operation*/
#include <bits/stdc++.h>
#define int long long
#define read(x) scanf("%lld", &x)
#define print(a, c) printf("%lld%c", a, c)
// #define ll long long
#define pb push_back
 
using namespace std;
const int maxn = 1e3 + 10;
const int maxm = 1e6 + 10;
const int inf = 2147483647;  // 1<<31-1
 
struct node {
    int to, w;
    node() {}
    node(int _to, int _w) { to = _to, w = _w; }
};
struct pii {
    int fi, se;
    pii() {}
    pii(int _fi, int _se) { fi = _fi, se = _se; }
    bool operator<(pii b) const { return fi > b.fi; }
};
priority_queue<pii> q;
int n, m;
int u, v, w;
vector<node> g[maxn];
int dis[maxn], vis[maxn], pre[maxn];
void dijkstra() {
    for (int i = 1; i <= n; i++) dis[i] = inf, vis[i] = 0, pre[i] = 0;
    dis[1] = 0, pre[1] = 1;
    q.push(pii(0, 1));
    while (!q.empty()) {
        pii now = q.top();
        q.pop();
        int d = now.fi, i = now.se;  //Distance and subscript
        if (vis[i])
            continue;  //It is normal that the previously marked points are still not taken out in the priority queue. They will be taken out at that time
        vis[i] = 1;
        for (auto j : g[i]) {
            if (vis[j.to]) continue;
            //Slack operation
            if (d + j.w == dis[j.to]) pre[j.to]++;  //Operation 1 step 1
            if (d + j.w < dis[j.to]) {
                dis[j.to] = d + j.w;
                q.push(pii(dis[j.to], j.to)), pre[j.to] = 1;  //Operation 1 step 2
            }
        }
    }
}
signed main() {
    read(n), read(m);
    for (int i = 1; i <= m; i++) {
        read(u), read(v), read(w);
        g[u].pb(node(v, w)), g[v].pb(node(u, w));
    }
    dijkstra();
    int ans = 1;
    // for (int i = 1; i <= n; i++) cout << i << ":::" << pre[i] << endl;
    for (int i = 1; i <= n; i++) ans = (ans * pre[i]) % inf;
    print(ans, '\n');
    return 0;
}

Does the shortest path tree size (sum of dis) change after removing one edge on the way

  1. Meaning: n n n cities ( n ≤ 100 ) (n\le 100) (n≤100), m m m undirected edges. The shortest path is taken between each two cities. Print the serial numbers of all roads from small to large. These roads meet the following requirements: after removing them, the distance between at least two cities becomes larger.
  2. Solution: for each starting point, build a shortest path tree respectively, and then enumerate each edge on the tree. Build a shortest path tree without passing through this edge, and find the sum of the shortest path from the starting point to each other point. If it is greater than the value before the edge is removed, the conditions must be met. Note: when enumerating any starting point, you can build any shortest path tree, because if it exists In multiple shortest path trees, if an edge enumerated at the same time can be replaced, they can replace each other. Removing any one will not change the shortest path sum!!!
  3. Code: it is attached. You can know the idea. The practice is still the shortest path + building the shortest path tree.

Just the above two applications for the time being. After all, I haven't encountered them

Shortest circuit count

  1. Concept: literally.
  2. Operation: it is almost the same as the operation of the shortest path tree. Only some changes need to be made: pre is initialized to 0; pre[s]=1; then, when dis[u]==dis[v], pre[v]+=pre[u]; when relaxation operation, pre[v]=pre[u] is ok.
  3. Compare the shortest path tree: pre is initialized to 0; pre[s]=1; then pre[v] + + every time dis[u]==dis[v] is encountered; it is ok when pre[v]=1 is relaxed.
  4. Example: P1608 path statistics
    1. Question meaning: n points, starting at 1, to reach n. ask how many are the shortest paths and how many are there. If there is no one, print No. n ≤ 2000 , m ≤ n ∗ ( n − 1 ) n\le 2000,m\le n*(n-1) N ≤ 2000,m ≤ n * (n − 1), no self ring and no double edge are guaranteed. In addition, all paths are unidirectional! - the double edge takes the minimum value, rather than if there are x lines to wait, it means that there are x ways to go.

Template

void dijkstra() {
    for (int i = 1; i <= n; i++) dis[i] = inf, vis[i] = 0, pre[i] = 0;
    dis[1] = 0, pre[1] = 1;
    q.push(pii(0, 1));  //Small top pile
    while (!q.empty()) {
        pii now = q.top();
        q.pop();
        int d = now.fi, i = now.se;  //Distance and subscript
        if (vis[i])
            continue;  //It is normal that the previously marked points are still not taken out in the priority queue. They will be taken out at that time
        vis[i] = 1;
        for (auto j : g[i]) {
            if (vis[j.to]) continue;
            //Slack operation
            if (d + j.w == dis[j.to]) pre[j.to] += pre[i];  //Operation one first step
            if (d + j.w < dis[j.to]) {
                dis[j.to] = d + j.w;
                q.push(pii(dis[j.to], j.to)),
                    pre[j.to] = pre[i];  //Operation 1 step 2
            }
        }
    }
    // dis[i]==inf, or pre[n]=0 indicates no path
    (dis[n] == inf) ? puts("No answer")
                    : (print(dis[n], ' '), print(pre[n], '\n'));
}

Layered graph shortest path (several cases of layered graph)

  1. Reference blog:
    1. Summary and classical examples of the shortest path of hierarchical graphs in graph theory
    2. Topic · shortest path [including Dijkstra, SPFA, Floyd, transitive closure, two-dimensional shortest path, layered graph, shortest path, shortest path count
  2. Introduction: it's just different when building a map. In addition, it's a common shortest circuit. Of course, the difficult thing is building a map.

Several cases of using hierarchical graph

  1. k edges of different sets. Build a floor map for each set, and then build a virtual map on the k+1 floor (used to connect each floor, the value according to the meaning of the topic). For example, take the subway in light rain.

  2. There are k opportunities to take one road for free. Build k+1 same maps, and connect each floor with edge points at a cost of 0. Not taking one floor means taking one opportunity. For example, P4568 [JLOI2011] flight route.

  3. There are k opportunities for reverse driving. Build k+1 same graphs. Each layer is connected by the reverse edge between two points with edges, and the weight remains unchanged. If you don't walk a layer, you have used an opportunity (it should be a directed graph, otherwise it doesn't make sense).

Example 1: Xiaoyu takes the subway

  1. Title Description: n ( 1 − 1000 ) n(1-1000) n (1 − 1000) stations, m ( 1 − 500 ) m(1-500) m (1 − 500) subway lines. It costs to pass the i subway line each time a i ( 1 − 100 ) a_i(1-100) ai (1 − 100), it costs more for each station on this subway line b i ( 1 − 100 ) b_i(1-100) bi (1 − 100), on each line c i ( 1 − n ) c_i(1-n) ci (1 − n) stations (input the stations along the way in sequence, note that it is bidirectional).
  2. Problem solution: situation 1. Note that it costs 0 when entering layer m+1, and only when entering layer m+1 a x ax ax (equivalent to from nm+s to nm+t). Read more questions and check for errors; Note the total number of points after drawing.
  3. code:
#include <bits/stdc++.h>
#define int long long
#define read(x) scanf("%lld", &x)
#define print(a, c) printf("%lld%c", a, c)
#define pb push_back
#define mst(a, x) memset(a, x, sizeof(a))
#define dbg(x) cout << #x << "===" << x << endl
using namespace std;
const int maxn = 500 * 1000 + 1000 + 10;
const int mod = 1e9 + 7;
const int inf = 1e9;
struct node {
    int to, w;
    node() {}
    node(int _to, int _w) { to = _to, w = _w; }
};
struct pii {
    int fi, se;  // dis,id
    pii() {}
    pii(int _fi, int _se) { fi = _fi, se = _se; }
    bool operator<(pii b) const {
        return fi > b.fi;
    }  //Usually, it's a big top pile, otherwise it's a small top pile. Here is a small top pile
};
int n, m, s, t;
int a, b, c;
vector<node> g[maxn];
int dis[maxn], vis[maxn];
priority_queue<pii> q;
 
void dijkstra(int s) {
    for (int i = 1; i <= n * m + n; i++) dis[i] = inf;
    dis[s] = 0, vis[s] = 1;
    q.push(pii(0, s));
    while (!q.empty()) {
        pii now = q.top();
        q.pop();
        int x = now.se, w = now.fi;
        for (auto i : g[x]) {
            if (i.w + dis[x] < dis[i.to]) {
                dis[i.to] = i.w + dis[x], vis[i.to] = 1;
                q.push(pii(dis[i.to], i.to));
            }
        }
    }
}
signed main() {
    read(n), read(m), read(s), read(t);
    for (int i = 1; i <= m; i++) {
        read(a), read(b), read(c);
        int now, pre;
        //Build the k-th drawing
        for (int j = 1; j <= c; j++) {
            read(now);
            if (j > 1) {
                int u = (i - 1) * n + pre, v = (i - 1) * n + now, w = b;
                g[u].pb(node(v, w));
                g[v].pb(node(u, w));
            }
            //Connected virtual diagram (equivalent to transfer station)
            int u = (i - 1) * n + now, v = n * m + now, w = a;
            g[u].pb(node(v, 0));  //0 is required for entry
            g[v].pb(node(u, w));  //Coming out represents entering a new line from one line (it costs money every time)
            pre = now;
        }
    }
    dijkstra(n * m + s);  //From n*m+t
    // for (int i = 1; i <= 10; i++) print(dis[i], ' ');
    // cout << endl;
    if (dis[n * m + t] == inf)
        puts("-1");
    else
        print(dis[n * m + t], '\n');
    return 0;
}

Title 2: P4568 [JLOI2011] flight route

  1. Title Link: P4568 [JLOI2011] flight route
  2. Meaning: n ( 2 − 1 e 4 ) n(2-1e4) n (2 − 1e4) points, m ( 1 − 5 e 4 ) m(1-5e4) m (1 − 5e4) undirected weighted edges 0 − 1 e 3 0-1e3 0 − 1e3), you can sit at most k ( 0 − 10 ) k(0-10) k (0 − 10) free flights. Ask the minimum cost from s to t.
  3. Problem solution: situation 2. Difficulties on the drawing under construction
  4. code:
#include <bits/stdc++.h>
#define int long long
#define read(x) scanf("%lld", &x)
#define print(a, c) printf("%lld%c", a, c)
#define pb push_back
#define mst(a, x) memset(a, x, sizeof(a))
#define dbg(x) cout << #x << "===" << x << endl
using namespace std;
const int maxn = 1e4 * 12 + +10;
const int mod = 1e9 + 7;
const int inf = 1e9;
struct node {
    int to, w;
    node() {}
    node(int _to, int _w) { to = _to, w = _w; }
};
struct pii {
    int fi, se;  // dis,id
    pii() {}
    pii(int _fi, int _se) { fi = _fi, se = _se; }
    bool operator<(pii b) const {
        return fi > b.fi;
    }  //Normal is large top pile, abnormal is small top pile
};
int n, m, k, s, t;
int u, v, w;
vector<node> g[maxn];
int dis[maxn], vis[maxn];
priority_queue<pii> q;
 
void dijkstra(int s) {
    for (int i = 0; i <= n * k + n; i++) dis[i] = inf;
    dis[s] = 0, vis[s] = 1;
    q.push(pii(0, s));
    while (!q.empty()) {
        pii now = q.top();
        q.pop();
        int x = now.se, w = now.fi;
        for (auto i : g[x]) {
            if (i.w + dis[x] < dis[i.to]) {
                dis[i.to] = i.w + dis[x], vis[i.to] = 1;
                q.push(pii(dis[i.to], i.to));
            }
        }
    }
}
signed main() {
    read(n), read(m), read(k);
    read(s), read(t);
    for (int i = 1; i <= m; i++) {
        read(u), read(v), read(w);
        // Floor 0 drawing
        g[u].pb(node(v, w)), g[v].pb(node(u, w));
        for (int j = 1; j <= k; j++) {
            // Floor 1~k
            g[j * n + u].pb(node(j * n + v, w));
            g[j * n + v].pb(node(j * n + u, w));
            //The upper layer is connected to this layer
            g[(j - 1) * n + u].pb(node(j * n + v, 0));
            g[(j - 1) * n + v].pb(node(j * n + u, 0));
        }
    }
    //Pass it to n*k+t, and finally directly take dis[n*k+t];
    for (int i = 1; i <= k; i++) g[(i - 1) * n + t].pb(node(i * n + t, 0));
    dijkstra(s);  //From n*m+t
    // for (int i = 0; i <= 10; i++) print(dis[i], ' ');
    // cout << endl;
    print(dis[n * k + t], '\n');
    return 0;
}
/*
5 6 1
0 4
0 1 5
1 2 5
2 3 5
3 4 5
2 3 3
0 2 100
*/

Situation 3: the difference from situation 2 is only in the construction of drawings. It's good to have this awareness.

  1. ps: not just with these applications.

k short circuit (template question)

  1. Title Link: Remmarguts' Date POJ - 2449
  2. Meaning: N ( 1 ≤ N ≤ 1000 ) (1\le N\le 1000) (1 ≤ N ≤ 1000) points, M ( 1 ≤ M ≤ 1 e 5 ) (1\le M\le 1e5) (1 ≤ M ≤ 1e5) directed weighted edge, k of points s to t$ ( 1 ≤ k ≤ 1000 ) (1\le k\le 1000) (1 ≤ k ≤ 1000) length of short circuit.
  3. Problem solution: k short circuit template problem. First, build a reverse path, dis[i] represents the shortest path to t, and then bfs, get t once and record the times once. See code for bfs specific operation.
  4. be careful:
    1. s may not reach t.
    2. There may be no k paths from s to t (if there are rings on any path of s-t, the paths from s to t can be regarded as countless).
    3. When s==t, k should be added with 1, because the first s in bfs is counted as t (length is 0).

Template 1

#include <string.h>
 
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
// #define int long long
#define read(x) scanf("%d", &x)
#define print(a, c) printf("%d%c", a, c)
#define pb push_back
#define mst(a, x) memset(a, x, sizeof(a))
#define dbg(x) cout << #x << "===" << x << endl
using namespace std;
const int maxn = 1e3 + 10;
const int mod = 1e9 + 7;
const int inf = 1e9;
struct node {
    int to, w;
    node() {}
    node(int _to, int _w) { to = _to, w = _w; }
};
struct pii {
    int i, dis, dis1;
    pii() {}
    pii(int _i, int _dis, int _dis1) { i = _i, dis = _dis, dis1 = _dis1; }
    bool operator<(pii b) const { return dis + dis1 > b.dis + b.dis1; }
};
 
int n, m, s, t, k;
int u, v, w;
vector<node> g[maxn], re[maxn];
int dis[maxn], vis[maxn];
void spfa(int s) {
    for (int i = 0; i <= n; i++) dis[i] = inf;
    dis[s] = 0;
    queue<int> q;
    q.push(s), vis[s] = 1;
    while (!q.empty()) {
        int x = q.front();
        q.pop();
        vis[x] = 0;
        // sbpoj and c++11 are not supported
        for (int j = 0; j < re[x].size(); j++) {
            node i = re[x][j];
            if (i.w + dis[x] < dis[i.to]) {
                dis[i.to] = i.w + dis[x];
                if (vis[i.to] == 0) q.push(i.to), vis[i.to] = 1;
            }
        }
    }
}
priority_queue<pii> q;
void bfs(int s) {
    q.push(pii(s, 0, 0));
    int cnt = 0;
    while (!q.empty()) {
        pii now = q.top();
        q.pop();
        if (now.i == t) {
            cnt++;
            if (cnt == k) {
                print(now.dis, '\n');
                return;
            }
        }
        for (int j = 0; j < g[now.i].size(); j++) {
            node i = g[now.i][j];
            q.push(pii(i.to, now.dis + i.w, dis[i.to]));
        }
    }
    puts("-1");  //What is this—— After all, there may be no k paths for S - > t
}
signed main() {
    read(n), read(m);
    for (int i = 1; i <= m; i++) {
        read(u), read(v), read(w);
        g[u].pb(node(v, w));
        re[v].pb(node(u, w));
    }
    read(s), read(t), read(k);
    spfa(t);
    if (dis[s] == inf)
        puts("-1");
    else {
        if (s == t) k++;  //Why? Look bfs where. s is also regarded as T. This t doesn't count
        bfs(s);
    }
    return 0;
}
/*
input:::
2 2
1 2 5
2 1 4
1 2 2
output:::
14
*/

Template 2 (if the number of the first k is required to be output)

#include <bits/stdc++.h>
// #define int long long
#define read(x) scanf("%d", &x)
#define print(a, c) printf("%d%c", a, c)
#define pb push_back
#define mst(a, x) memset(a, x, sizeof(a))
#define dbg(x) cout << #x << "===" << x << endl
using namespace std;
const int maxn = 1e3 + 10;
const int mod = 1e9 + 7;
const int inf = 1e9;
struct node {
    int to, w;
    node() {}
    node(int _to, int _w) { to = _to, w = _w; }
};
struct pii {
    int i, dis, dis1;
    pii() {}
    pii(int _i, int _dis, int _dis1) { i = _i, dis = _dis, dis1 = _dis1; }
    bool operator<(pii b) const { return dis + dis1 > b.dis + b.dis1; }
};
 
int n, m, k;
int u, v, w;
vector<node> g[maxn], re[maxn];
vector<int> ans;
int dis[maxn], vis[maxn];
void spfa(int s) {
    for (int i = 0; i <= n; i++) dis[i] = inf;
    dis[s] = 0;
    queue<int> q;
    q.push(s), vis[s] = 1;
    while (!q.empty()) {
        int x = q.front();
        q.pop();
        vis[x] = 0;
        for (int j = 0; j < re[x].size(); j++) {
            node i = re[x][j];
            if (i.w + dis[x] < dis[i.to]) {
                dis[i.to] = i.w + dis[x];
                if (vis[i.to] == 0) q.push(i.to), vis[i.to] = 1;
            }
        }
    }
}
priority_queue<pii> q;
void bfs(int s) {
    q.push(pii(s, 0, 0));
    int cnt = 0;
    while (!q.empty()) {
        pii now = q.top();
        q.pop();
        if (now.i == 1) {
            cnt++;
            ans.pb(now.dis);
            if (cnt == k) return;
        }
        for (int j = 0; j < g[now.i].size(); j++) {
            node i = g[now.i][j];
            q.push(pii(i.to, now.dis + i.w, dis[i.to]));
        }
    }
    while (ans.size() < k) ans.pb(-1);
}
signed main() {
    read(n), read(m), read(k);
    for (int i = 1; i <= m; i++) {
        read(u), read(v), read(w);
        g[u].pb(node(v, w));
        re[v].pb(node(u, w));
    }
    spfa(1);
    if (dis[n] == inf)
        for (int i = 1; i <= k; i++) ans.pb(-1);
    else {
        if (n == 1) k++;  //Why? Look bfs where. s is also regarded as T. This t doesn't count
        bfs(n);
    }
    for (auto i : ans) print(i, '\n');
    return 0;
}
/*
input:::
5 8 7 
5 4 1 
5 3 1 
5 2 1 
5 1 1 
4 3 4 
3 1 1 
3 2 1 
2 1 1 
output:::
1 
2 
2 
3 
6 
7 
-1 
*/

Minimum spanning tree (used with kuangbin board)

Network flow

Template 1: chain forward star

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int M = 1e5 + 10;

int cnt, head[N];  // cnt is initialized to 0 and head is initialized to - 1
//structural morphology
struct Edge {
    int to, w, next;
    Edge(int to = 0, int w = 0, int next = 0) : to(to), w(w), next(next) {}
} edge[M];
//Edging
void add(int u, int v, int w) {
    edge[cnt] = Edge(v, w, head[u]), head[u] = cnt++;  //Positive edge
    edge[cnt] = Edge(u, w, head[v]), head[v] = cnt++;
    //Reverse edge (pay attention to the weight, according to the requirements of the topic)
    /*    It is recommended to start all from 0. There seems to be a problem with the network flow from 1. CNT starts from 1: edge[++cnt]=Edge(v,w,head[u]),head[u]=cnt;*/
}
//Traversal: for(int i=head[u];~i;i=edge[i].next)
void init() { memset(head, 0, sizeof(head)), cnt = 0; }

signed main() {
    init();
    return 0;
}

Template 2: Dinic (Dinic should be the most commonly used, not much slower than ISAP)

//The title is still the title of EK above.
#include <bits/stdc++.h>

// #define int long long
#define read(x) scanf("%d", &x)
#define print(a, c) printf("%d%c", a, c)
#define pb push_back
#define dbg(x) cout << #x << "===" << x << endl
using namespace std;
const int M = 2e2 + 10;
const int INF = 1e9 + 10;

struct Edge {
    int to, w, next;
    Edge(int to = 0, int w = 0, int next = 0) : to(to), w(w), next(next) {}
} e[M << 1];
int n, m, a, b, c;
int s, t;
int head[M], cnt;
void add(int u, int v, int w) {
    e[cnt] = Edge(v, w, head[u]), head[u] = cnt++;
    e[cnt] = Edge(u, 0, head[v]), head[v] = cnt++;
}
int dep[M], now[M];
// bfs enables dfs to be expanded and optimized according to dep (I can't understand the specific proof).
bool bfs() {
    memset(dep, -1, sizeof(dep));
    queue<int> q;
    q.push(s), dep[s] = 0;
    now[s] = head[s];  //Current arc optimization (initialization)
    while (!q.empty()) {
        int x = q.front();
        q.pop();
        for (int i = now[x]; ~i; i = e[i].next) {
            int v = e[i].to;
            if (dep[v] == -1 && e[i].w > 0) {
                dep[v] = dep[x] + 1;
                now[v] = head[v];  //Current arc optimization (initialization).
                q.push(v);
                if (v == t) return true;
                //Exit when v==t is encountered, because < dep [v] has been traversed, and the augmented path of dfs cannot pass through the point with depth > = dep [v]
            }
        }
    }
    return false;
}
//There may be several expansion paths for a dfs: see figure
int dfs(int x, int flow) {
    if (x == t) return flow;
    int ans = 0;
    // Flow represents the flow that can be operated at point x, and ans represents the total maximum flow of X after the expansion
    // If there is no flow left, there is no need to expand it
    for (int i = now[x]; ~i && flow; i = e[i].next) {
        int v = e[i].to;
        now[x] = i;
        //Current arc optimization (it can only be optimized here, and only initialization in bfs: now[x]=head[x])
        if (dep[v] == dep[x] + 1 && e[i].w > 0) {
            int tmp = dfs(v, min(flow, e[i].w));
            // tmp is the maximum flow through point v
            if (tmp == 0) dep[v] = -1;  //Prune and remove the enlarged point
            e[i].w -= tmp;
            e[i ^ 1].w += tmp;
            ans += tmp;
            flow -= tmp;  //Flow accumulation (backtracking) through the current point (x)
        }
    }
    return ans;  //The last thing to return is the increased traffic and
}
int Dinic() {
    int maxflow = 0;
    // If bfs is true, dfs multi-channel augmentation will continue
    while (bfs()) maxflow += dfs(s, INF);
    return maxflow;
}
signed main() {
    read(n), read(m);
    memset(head, -1, sizeof(head));
    s = 1, t = m;
    for (int i = 1; i <= n; i++) {
        read(a), read(b), read(c);
        add(a, b, c);
    }
    print(Dinic(), '\n');
    return 0;
}

ISAP (finally getting to the point? & faster board than Dinic)

// Luogu _P2740 [USACO4.2] grassland Drainage Ditches
#include <bits/stdc++.h>
// #define int long long
#define read(x) scanf("%d", &x)
#define print(a, c) printf("%d%c", a, c)
#define dbg(x) cout << #x << "===" << x << endl
using namespace std;
const int N = 2e2 + 10;
const int M = 4e2 + 10;  //It's more comfortable to operate directly here. M < < 1 is easy to make mistakes
const int INF = 1e9 + 7;
int n, m, s, t, a, b, c;
struct Edge {
    int v, w, next;
    Edge(int v = 0, int w = 0, int next = 0) : v(v), w(w), next(next) {}
} e[M];
int head[N], cnt, now[N];
void add(int u, int v, int w) {
    e[cnt] = Edge(v, w, head[u]), head[u] = cnt++;
    e[cnt] = Edge(u, 0, head[v]), head[v] = cnt++;
}
int dep[N], gap[N];  // gap Optimization: it seems that the optimization is very strong
void bfs() {
    for (int i = 0; i <= n; i++) dep[i] = gap[i] = 0, now[i] = head[i];
    queue<int> q;
    q.push(t), dep[t] = 1, gap[dep[t]]++;
    while (!q.empty()) {
        int x = q.front();
        q.pop();
        for (int i = head[x]; ~i; i = e[i].next) {
            int v = e[i].v;
            if (!dep[v]) dep[v] = dep[x] + 1, q.push(v), gap[dep[v]]++;
        }
    }
}
int dfs(int x, int flow) {
    if (x == t) return flow;
    int ans = 0;
    for (int i = now[x]; ~i; i = e[i].next) {
        int v = e[i].v;
        now[x] =
            i;  //How do you always forget the operation of arc optimization? Even i=head[i] is here? Alas, it's still too delicious
        if (dep[x] == dep[v] + 1) {
            int tmp = dfs(v, min(flow, e[i].w));
            //Compared with Dinic, if there is no tmp==0, dep[v]=INF. If there is pruning here, it obviously destroys the value of Dep. You need to update dep from the new bfs
            e[i].w -= tmp;
            e[i ^ 1].w += tmp;
            ans += tmp;
            flow -= tmp;
            if (!flow) return ans;
            // x didn't finish running, so it can't jump out and return to ans like Dinic. V point is finished running, but the previous layer of dfs has been modified dep[v]
            // Dinic is ~i&&flow. In fact, dinic can also write like here
        }
    }
    //The operation above is as like as two peas (Dinic), which is a little different from Dinic, and no pruning!!!
    //The following understanding comes from https://www.luogu.com.cn/blog/ONE-PIECE/jiu-ji-di-zui-tai-liu-suan-fa-isap-yu-hlpp
    //By the time we get here, all the points where x flows out have already flowed
    //But the point flowing from the front is still left. Change dep to separate x from the point where x flows out
    // emmm, although not fully understood, knows how to operate. Although it knows how to operate, it does not fully understand
    //Come back later
    gap[dep[x]]--;  //Why is this place dep[x]+ +?
    if (gap[dep[x]] == 0) dep[s] = n + 1;
    ++gap[++dep[x]], now[x] = head[x];  //For the current arc optimization, return to the head after each layering
    return ans;
}
int ISAP() {
    int res = 0;
    bfs();
    // dbg(dep[s]); Is there any error in BFS
    while (dep[s] <= n && dep[s]) res += dfs(s, INF);
    return res;
}
void init() {
    memset(head, -1, sizeof(head)), cnt = 0;
    read(m), read(n);  // m is the number of edges and n is the number of points
    s = 1, t = n;
    for (int i = 1; i <= m; i++) {
        read(a), read(b), read(c);
        add(a, b, c);
    }
}
signed main() {
    init();
    int maxflow = ISAP();
    print(maxflow, '\n');
    return 0;
}

Print separately (approximate rate is the common version - not limited to icpc):

number theory

Summary of number theory

Graph theory -- tree chain subdivision & multiplication for LCA

Tree chain subdivision Learning & summary

data structure

Data structure summary

character string

String Learning & summary (mainly the summary template)

Computational geometry

Rotating chuck & convex hull (you don't have to learn all at once)

Tags: C C++

Posted on Fri, 12 Nov 2021 23:12:19 -0500 by unmash