弱弱的模板啦啦啦

一些水水的模板啦啦(还在更..)

强连通分量缩点

BZOJ1051 [HAOI2006]受欢迎的牛

[HAOI2006]受欢迎的牛 の 传送门
强连通分量缩点模板题

//bzoj1051
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
#include <stack>
using namespace std;

const int N = 10007, M = 50007;
int n, m, cnt, scc, tim, ans, head[N], to[M], nxt[M], low[N], dfn[N], belong[N], vis[N], hav[N], chu[N];
stack <int> S;

inline int read(){
    int ans = 0, f = 1;
    char ch = getchar();
    for(; ch < '0' || ch > '9'; ch = getchar())
        if (ch == '-')
            f = 0;
    for(; ch >= '0' && ch <= '9'; ch = getchar())
        ans = (ans << 3) + (ans << 1) + ch - 48;
    return f? ans: -ans;
}
void add(int u, int v){
    nxt[++cnt] = head[u];
    to[cnt] = v;
    head[u] = cnt;
}
void tarjan(int u){
    dfn[u] = low[u] = ++tim;
    S.push(u);
    vis[u] = 1;
    int v;
    for (int i = head[u]; i; i = nxt[i]){
        v = to[i];
        if (!dfn[v])
            tarjan(v), low[u] = min(low[u], low[v]);
        else
            if (vis[v])
                low[u] = min(low[u], dfn[v]);
    }
    if (dfn[u] == low[u]){
        scc++;
        do {
            v = S.top();
            vis[v] = 0;
            belong[v] = scc;
            hav[scc]++;
            S.pop();
        } while(u != v);
    }
}
int main(){
    tim = cnt = scc = 0;
    n = read(), m = read();
    while (S.size())
        S.pop();
    for (register int i = 1; i <= m; ++i){
        int u = read(), v = read();
        add(u, v);
    }
    for (register int i = 1; i <= n; ++i)
        if (!dfn[i]) tarjan(i);
    for (register int k = 1; k <= n; ++k)
        for (int i = head[k]; i; i = nxt[i]){
            int v = to[i];
            if (belong[k] != belong[v])
                chu[belong[k]]++;
        }    
    ans = 0;
    for (int i = 1; i <= scc; ++i){
        if (!chu[i]){
            if (ans){
                printf("0\n");
                return 0;
            }
            else
                ans = hav[i];
        }
    }
    printf("%d\n", ans);
    return 0;
}

树上倍增求LCA

luogu3379

luogu3379 最近公共祖先 の 传送门

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#define ll long long
using namespace std;

const int N = 500007, M = 500007;
int cnt, n, m, s, head[N], dep[N], fa[N][22], nxt[M << 1], to[M << 1]; 
inline int read(){
    int ans = 0, f = 1;
    char ch = getchar();
    for(; ch < '0' || ch > '9'; ch = getchar())
        if (ch == '-')
            f = 0;
    for(; ch >= '0' && ch <= '9'; ch = getchar())
        ans = (ans << 3) + (ans << 1) + ch - 48;
    return f? ans: -ans;
}
void add(int u, int v){
    nxt[++cnt] = head[u];
    to[cnt] = v;
    head[u] = cnt;
}
void dfs(int u, int father){
    dep[u] = dep[father] + 1;
    fa[u][0] = father;
    for (int i = head[u]; i; i = nxt[i]){
        int v = to[i];
        if (v != father)
            dfs(v, u);
    }
}
int lca(int x, int y){
    if (dep[x] < dep[y])
        swap(x, y);
    int z = dep[x] - dep[y];
    for (int i = 0; i <= 20; ++i)
        if (z & (1 << i))
            x = fa[x][i];
    for (int i = 20; i >= 0; --i)
        if (fa[x][i] != fa[y][i]){
            x = fa[x][i];
            y = fa[y][i];
        }
    if (x == y)
        return x;
    return fa[x][0];
}
int main(){
    n = read(), m = read(), s = read();
    for (int i = 1; i < n; ++i){
        int u = read(), v = read();
        add(v, u);
        add(u, v);
    }
    dfs(s, 0);
    for (int j = 1; (1 << j) <= n; ++j)
    for (int i = 1; i <= n; ++i)
        fa[i][j] = fa[fa[i][j - 1]][j - 1];
    for (int i = 1; i <= m; ++i){
        int x = read(), y = read();
        printf("%d\n", lca(x, y));
    }
    return 0;
}

最小生成树

Prim O(n^2)

luogu3366

luogu3366 最小生成树 の 传送门

//luogu3366
//Prim
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#define ll long long
using namespace std;

const int N = 5007, M = 200007, oo = 1e9 + 7;
int n, m, cnt, num, head[N], to[M << 1], nxt[M << 1], val[M << 1], ans, dis[N];
bool vis[N];

inline int read(){
    int ans = 0, f = 1;
    char ch = getchar();
    for(; ch < '0' || ch > '9'; ch = getchar())
        if (ch == '-')
            f = 0;
    for(; ch >= '0' && ch <= '9'; ch = getchar())
        ans = (ans << 3) + (ans << 1) + ch - 48;
    return f? ans: -ans;
}
void add(int u, int v, int w){
    nxt[++cnt] = head[u];
    to[cnt] = v;
    val[cnt] = w;
    head[u] = cnt;
}
void prim(){
    memset(vis, false, sizeof(vis));
    ans = 0;
    dis[1] = 0;
    for (int i = 2; i <= n; ++i)
        dis[i] = oo;
    num = 0;
    while (num < n){
        ++num;
        int minn = oo, now = -1;
        for (int i = 1; i <= n; ++i)
            if (!vis[i] && dis[i] < minn){
                minn = dis[i];
                now = i;
            }
        if (now == -1){
            ans = -1;
            return;
        }
        vis[now] = 1;
        ans += dis[now];
        for (int i = head[now]; i; i = nxt[i]){
            int v = to[i];
            if (!vis[v])
                dis[v] = min(dis[v], val[i]);
        }
    }
}
int main(){
    memset(head, 0, sizeof(head));
    n = read(), m = read();
    for (int i = 1; i <= m; ++i){
        int u = read(), v = read(), w = read();
        add(v, u, w);
        add(u, v, w);
    }
    prim();
    if (ans == -1)
        printf("orz\n");
    else
        printf("%d\n", ans);
    return 0;
}

Kruskal O(e*log e)

luogu3366

luogu3366 最小生成树 の 传送门

//luogu3366
//Kruskal
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#define ll long long
using namespace std;

const int N = 5007, M = 200007, oo = 1e9 + 7;
int n, m, fa[N], cnt, ans;
struct iG{
    int x, y, val;
} a[M];

inline int read(){
    int ans = 0, f = 1;
    char ch = getchar();
    for(; ch < '0' || ch > '9'; ch = getchar())
        if (ch == '-')
            f = 0;
    for(; ch >= '0' && ch <= '9'; ch = getchar())
        ans = (ans << 3) + (ans << 1) + ch - 48;
    return f? ans: -ans;
}
inline bool cmp(iG a, iG b){
    return a.val < b.val;
}
inline int find(int x){
    return fa[x] == x ? x: fa[x] = find(fa[x]);
}
inline void kruskal(){
    sort(a + 1, a + 1 + m, cmp);
    for (register int i = 1; i <= n; ++i)
        fa[i] = i;
    for (register int i = 1; i <= m; ++i){
        int fx = find(a[i].x), fy = find(a[i].y);
        if (fx != fy){
            ans += a[i].val;
            fa[fx] = fy;
            cnt++;
            if (cnt == n - 1)
                break;
        }
    }
}
int main(){
    n = read(), m = read();
    for (int i = 1; i <= m; ++i){
        a[i].x = read(), a[i].y = read(), a[i].val = read();
    }
    kruskal();
    if (cnt == n - 1)
        printf("%d\n", ans);
    else
        printf("orz\n");
    return 0;
}

次小生成树

k小生成树

KMP

AC自动机

猜你喜欢

转载自www.cnblogs.com/df015/p/9858677.html
今日推荐