模板大集结!

好久不碰OI了,最近决定把各种基础算法的模板和用法整理下。

·SPFA
-求瓶颈路 洛谷 1396
-求最短路 好多。。
-路上最值 洛谷 1073
-边的特殊处理 eg. 加入点出点 暑末Day2 T1
-判负环 可结合分数规划食用

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1010;
const int inf = 0x3f3f3f3f;

struct node{
    int v, w, nxt;
} edge[maxn*maxn*2];

int dis[maxn], vis[maxn], st[maxn];
int n, m, tot;
queue<int> q;

inline void in(int x, int y, int z){
    edge[++tot].v = y;
    edge[tot].w = z;
    edge[tot].nxt = st[x];
    st[x] = tot;
}

inline void SPFA(){
    for(int i = 0; i <= n; i++)
        dis[i] = inf;
    vis[1] = 1;
    dis[1] = 0;
    q.push(1);
    while(!q.empty()){
        int now = q.front(); q.pop();
        vis[now] = 0;
        for(int i = st[now]; i; i = edge[i].nxt){
            int to = edge[i].v;
            if(!vis[to] && dis[to] > dis[now] + edge[i].w){
                dis[to] = dis[now] + edge[i].w;
                vis[to] = 1;
                q.push(to);
            }
        }
    }
    printf("%d\n", dis[n]);
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1, x, y, z; i <= m; i++){
        scanf("%d%d%d", &x, &y, &z);
        in(x, y, z);
    }
    SPFA();
    return 0;
}

·Dijkstra
-稠密图最短路!
-有关贪心的图论 洛谷 1875

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1010;
const int inf = 0x3f3f3f3f;

struct data{
    int v, w, nxt;
} edge[maxn*maxn*2];

struct node{
    int point, w;
    bool operator < (const node& a) const {
        return w < a.w;
    }
};

int dis[maxn], vis[maxn], st[maxn];
int n, m, tot;
queue<int> q;

inline void in(int x, int y, int z){
    edge[++tot].v = y;
    edge[tot].w = z;
    edge[tot].nxt = st[x];
    st[x] = tot;
}

inline void Dijkstra(){
    priority_queue<node> q;
    for(int i = 0; i <= n; i++) dis[i] = inf;
    q.push((node){1, 0});
    dis[1] = 0;
    while(!q.empty()){
        node now = q.top(); q.pop();
        if(vis[now.point])  continue;
        vis[now.point] = 1;
        for(int i = st[now.point]; i; i = edge[i].nxt){
            int to = edge[i].v;
            if(dis[to] > dis[now.point] + edge[i].w){
                dis[to] = dis[now.point] + edge[i].w;
                q.push((node){to, dis[to]});
            }
        }
    }
    printf("%d\n", dis[n]);
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1, x, y, z; i <= m; i++){
        scanf("%d%d%d", &x, &y, &z);
        in(x, y, z);
    }
    Dijkstra();
    return 0;
}

·Kruskal
-瓶颈生成树 货车运输

#include<bits/stdc++.h>
using namespace std;

const int maxn = 5050;
const int maxm = 200020;

struct node{
    int x, y, w;
    //bool operator < (const node &p) const{ return w < p.w; }
} a[maxm];

int n, m, fa[maxn];

inline void getInit(){
    for(int i = 0; i <= n; i++) fa[i] = i;
}

inline int find(int x){
    if(x == fa[x])  return x;
    return fa[x] = find(fa[x]);
}

inline void merge(int x, int y){
    fa[find(x)] = find(y);
}

inline bool cmp(node p, node q){
    return p.w < q.w;
}

inline void Kruskal(){
    int sum = 0, tot = 0;
    getInit();
    sort(a+1, a+m+1, cmp);
    for(int i = 1; i <= m; i++){
        int fx = find(a[i].x);
        int fy = find(a[i].y);
        if(fx != fy){
            merge(fx, fy);
            sum += a[i].w;
            tot++;
        }
        //else break;
    }
    if(tot >= n-1)  printf("%d\n", sum);
    else printf("orz\n");
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; i++)
        scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].w);
    Kruskal();
    return 0;
}

·Tarjan
-求强联通分量
-缩点

#include<cstdio>
#include<iostream>
using namespace std;

const int maxn = 200050;

struct node{
    int v, nxt;
} edge[maxn];

int stack[maxn], dfn[maxn], low[maxn], sum[maxn], belong[maxn], st[maxn];
int n, m, a, b, t, tot, top, index, bcnt;
bool instack[maxn];

inline void in(int x, int y){
    edge[++tot].v = y;
    edge[tot].nxt = st[x];
    st[x] = tot;
}

inline void Tarjan(int u){
    stack[top++] = u;
    instack[u] = 1;
    dfn[u] = low[u] = ++index;
    for(int i = st[u]; i; i = edge[i].nxt){
        int to = edge[i].v;
        if(!dfn[to]){
            Tarjan(to);
            low[u] = min(low[u], low[to]);
        }
        else if(instack[to])
            low[u] = min(dfn[to], low[u]);
    }
    if(dfn[u] == low[u]){
        bcnt++;
        int to;
        do{
            to = stack[--top];
            sum[bcnt]++;
            belong[to] = bcnt;
            instack[to] = 0;
        } while(u != to);
    }
}

int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i++){
        scanf("%d", &b);
        in(i, b);
    }
    for(int  i = 1; i <= n; i++)
        if(!dfn[i]) Tarjan(i);
} 

·拓扑排序
-删边找环

#include<bits/stdc++.h>
using namespace std;

const int maxn = 200005;

int n, tot;
int st[maxn], vis[maxn], rd[maxn];
queue<int> q;

struct node{
    int v, nxt;
} edge[maxn*2];

inline void in(int x, int y){
    edge[++tot].v = y;
    edge[tot].nxt = st[x];
    st[x] = tot;
}

inline void Topsort(){
    for(int i = 1; i <= n; i++)
        if(!rd[i]){
            vis[i] = 1;
            q.push(i);
        }
    while(!q.empty()){
        int now = q.front(); q.pop();
        for(int i = st[now]; i; i = edge[i].nxt){
            int to = edge[i].v;
            if(rd[to] == 1){
                rd[to]--;
                vis[to] = 1;
                q.push(to);
            }
        }
    }
}

int main(){
    scanf("%d", &n);
    for(int i = 1, y; i <= n; i++){
        scanf("%d", &y);
        in(i, y);
        rd[y]++;
    }
    Topsort();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值