图论

拓扑排序

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

constexpr int N = 100010;
int n, m, a, b;
vector<int> e[N], tp;
int din[N];

bool toposort(){
    queue<int> q;
    for (int i = 1; i <= n; i++) if (din[i] == 0) q.push(i);
    while (q.size()){
        int x = q.front(); q.pop();
        tp.push_back(x);
        for (auto y : e[x]) {
            if(--din[y] == 0) q.push(y);
        }
    }
    return ((int)tp.size() == n);
}

int main(){
    cin >> n >> m;
    for (int i = 0; i < m; i++) {
        cin >> a >> b;
        e[a].push_back(b);
        din[b]++;
    }
    if(!toposort()) cout << "Yes";
    else cout << "No";
    return 0;
}

BellmanFord最短路

struct Edge{
  int x, y, val;
}edge[M+1];
int n, m, dist[M+1], pre[M+1];
int shortestPath(int s, int t){
  memset(dist, 127, sizeof(dist));
  dist[s]=0; bool ok=1;
  while(ok){
    ok=0;
    for(int i=1;i<=m;i++){
      int x = edge[i].x, y = edge[i].y, v = edge[i].val;
      if(dist[x] < (1<<30)){
        if(dist[x] + v < dist[y]){
          dist[y] = dist[x] + v;
          pre[y] = x;
          ok = 1;
        }
      }
    }
  }
  return dist[t];
}

Dijkstra最短路

struct edge{
  int v, w;
};
vector<edge> e[N];
int dist[N], vis[N];
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;        
void dijkstra(int s, int n) {
    for (int i = 0; i <= n; i++) dist[i] = INF, vis[i] = 0;
    dist[s] = 0;
    q.push({dist[s], s});
    while (q.size()) {
        auto t = q.top(); q.pop();
        int u = t.second;
        if (vis[u]) continue;
        vis[u] = 1;
        for (auto ed : e[u]) {
            int v = ed.v, w=ed.w;
            if (dist[v] > dist[u] + w){
              dist[v] = dist[u] + w;
              q.push({dist[v], v});
            }
        }
    }
}

Kruskal最小生成树

struct edge{
  int u, v, w;
  bool operator< (const edge &t) const {
    return w < t.w;
  }   
}e[N];
int fa[N], ans, cnt;
int find(int x){
  if(fa[x] == x) return x;
  return fa[x] = find(fa[x]);
}
bool kruskal(){
  sort(e, e + m);
  for(int i = 1; i <= n; i++) fa[i] = i;
  for(int i = 0; i < m; i++){
    int x = find(e[i].u);
    int y = find(e[i].v);
    if (x != y) {
      fa[x] = y;
      ans += e[i].w;
      cnt++;
    }
  } 
  return cnt == n - 1;
}

Prim最小生成树

struct edge{int v,w;};
vector<edge> e[N];
int minTree,cnt;
int d[N], vis[N];
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> q;
bool prim(int s){
  for(int i = 0; i <= n; i++) d[i] = INF;
  d[s] = 0; q.push({d[s],s});
  while(q.size()){
    int u=q.top().second; q.pop();
    if(vis[u]) continue;
    vis[u]=1;
    minTree += d[u]; cnt++;
    for(auto ed : e[u]){
      int v = ed.v, w=ed.w;
      if(d[v] > w){
        d[v] = w;
        q.push({d[v], v});
      }
    }
  }
  return cnt==n;
}

强连通分量(tarjan)

vector<int> e[N];
int dfn[N], low[N], ins[N], bel[N], idx, n, m, cnt;
stack<int> stk;
vector<vector<int>> scc;

void dfs(int u) { 
    dfn[u] = low[u] = ++idx;
    ins[u] = 1;
    stk.push(u);
    for(auto v : e[u]){
        if(!dfn[v]){
            dfs(v);
            low[u] = min(low[u], low[v]);
        }else{
            if(ins[v]) low[u] = min(low[u], dfn[v]);
        }
    }
    if(dfn[u] == low[u]){
        vector<int> c;
        ++cnt;
        while(true){
            int v = stk.top();
            c.push_back(v);
            ins[v] = false;
            bel[v] = cnt;
            stk.pop();
            if(v == u) break;
        }
        sort(c.begin(), c.end());
        scc.push_back(c);
    }
}

强连通分量(kasaraju)

vector<int> e[N], erev[N];
int dfn[N], low[N], ins[N], bel[N], idx, n, m, cnt;
bool vis[N];
stack<int> stk;
vector<vector<int>> scc;
vector<int> out, c;

void dfs(int u){
    vis[u]=true;
    for(auto v : e[u]){
        if(!vis[v]) dfs(v);
    }
    out.push_back(u);
}

void dfs2(int u){
    vis[u]=true;
    for(auto v : erev[u]){
        if(!vis[v]) dfs2(v);
    }
    c.push_back(u);
}

void work() {
    for (int i=1; i<=n; i++) {
        if(!vis[i]) dfs(i);
    }
    reverse(out.begin(), out.end());
    memset(vis, 0, sizeof(vis));
    for(auto u : out) if(!vis[u]) {
        c.clear();
        dfs2(u);
        scc.push_back(c);
    }
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> m;
    for (int i = 0; i < m; i++) {
        int u,v;
        cin >> u >> v;
        e[u].push_back(v);
        erev[v].push_back(u);
    }
    work();
    return 0;
}

割边

vector<array<int, 2>> e[N];
int dfn[N], low[N], idx, n, m;
vector<int> bridge;

void dfs(int u, int id) { 
    dfn[u] = low[u] = ++idx;
    for(auto z : e[u]){
        v = z[0], id2 = z[1];
        if (!dfn[v]) dfs(v, id2);
        if (id != id2) low[u] = min(low[u], low[v]);
    }
    if(dfn[u] == low[u] && id != -1){
        bridge.push_back(id + 1);
    }
}
//dfs(1, -1)

割点

vector<int> e[N];
int dfn[N], low[N], idx, n, m, sz;
bool cut;

void dfs(int u, int f) { 
    dfn[u] = low[u] = ++idx;
    int ch = 0;
    for(auto v : e[u]){
        if (!dfn[v]) {
            dfs(v, u);
            ch++;
            low[u] = min(low[u], low[v]);
            if (low[u] >= dfn[u]) cut[u] = 1;
        } else if (v != f) {
            low[u] = min(low[u], low[v]);
        }
    }
    if(u == 1 && ch <= 1){
        cut[u] = 0;
    }
    sz += cut[u];
}
//dfs(1, 0)

二分图

#include<bits/stdc++.h>
using namespace std;
constexpr int N = 1100;
vector<int> edge[N+1];
int n, m, c[N + 1];
bool dfs(int x){
    for(auto y : edge[x]){
        if(!c[y]) {
            c[y] = 3 - c[x];
            if(!dfs(y)){
                return false;
            }
        } else {
            if(c[x] == c[y]) return false;
        }
    }
    return true;
}
bool check(){
    memset(c, 0 ,sizeof c);
    for (int i = 1; i <= n; i++) {
        if (!c[i]) {
            c[i] = 1;
            if (!dfs(i)) return false;
        }
    }
    return true;
}
int main(){
    ios::sync_with_stdio(0); cin.tie(0);
    cin>>n>>m;
    for(int i = 1; i <= m; i++){
        int u, v; cin>>u>>v;
        edge[u].push_back(v);
        edge[v].push_back(u);
    }
    if(check()){
        cout<<"Yes";
    }else{
        cout<<"No";
    }
    return 0;
}

二分图最大匹配

int n, m;
vector<int> e[N+1];//L to R
int n1, n2, v[N+1];
bool b[N+1];
bool find(int x){
  b[x] = true;
  for(auto y : e[x]){
    if(!v[y] || (!b[v[y]]&&find(v[y]))){
      v[y] = x;
      return true;
    }
  }
  return false;
}
int match(){
  int ans = 0;
  memset(v, 0, sizeof(v));
  for(int i = 1; i <= n1; i++){
    memset(b, false, sizeof(b));
    if(find(i)) ++ans;
  }
  return ans;
}

 

posted @ 2024-03-21 19:50  Miburo  阅读(20)  评论(0)    收藏  举报