自备ACM模板 —— 图论篇

最小费用最大流

// SPFA跑费用流 洛谷 P3381
#include<bits/stdc++.h>
using namespace std;
#define maxn 5005
int read(){
    char c=getchar();
    int f = 1, ans = 0;
    while(c < '0' || c > '9'){
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9'){
        ans = ans*10 + c - '0';
        c = getchar();
    }
    return ans*f;
}
int s, t, cost[maxn], head[maxn], vis[maxn], flow[maxn], pre[maxn], last[maxn], cnt = -1;
struct node{
    int to, next, cost, flow;
}p[maxn*20];
queue<int> q;
void add(int x, int y, int f, int c){
    p[++cnt].next = head[x];
    head[x] = cnt;
    p[cnt].cost = c;
    p[cnt].flow = f;
    p[cnt].to = y;
}
bool spfa(){
    memset(vis, 0, sizeof(vis));
    memset(cost, 0x7f, sizeof(cost));
    flow[s] = 0x7ffffff;
    q.push(s), vis[s] = 1, cost[s] = 0, pre[t] = -1;
    while(!q.empty()){
        int now = q.front();
        q.pop();
        vis[now] = 0;
        for(int k = head[now]; k != -1; k = p[k].next){
            int x = p[k].to;
            if(p[k].flow > 0 && cost[x] > cost[now] + p[k].cost){
                cost[x] = cost[now] + p[k].cost;
                pre[x] = now;
                last[x] = k;
                flow[x] = min(flow[now], p[k].flow);
                if(!vis[x]){
                    vis[x] = 1;
                    q.push(x);
                }
            }
        }
    }
    return pre[t] != -1;
}
int maxflow, mincost;
void MCMF(){
    while(spfa()){
        int now = t;
        maxflow += flow[t];
        mincost += flow[t]*cost[t];
        while(now != s){
            p[last[now]].flow -= flow[t];
            p[last[now]^1].flow += flow[t];
            now = pre[now];
        }
    }
}

int main(){
    memset(head, -1, sizeof(head));
    int n, m, x, y, c, f;
    n = read(), m = read(), s = read(), t = read();
    for(int i = 1; i <= m; i++){
        x = read(), y = read(), f = read(), c = read();
        add(x, y, f, c);add(y, x, 0, -c);
    }
    MCMF();
    printf("%d %d\n",maxflow,mincost);
return 0;}

Dinic

// 洛谷 P3376
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long LL;
const int maxn = 1e3 + 5;
const int inf = 1<<30;

int n, m, s, t, cnt;
int head[maxn], cur[maxn], dep[maxn];

queue<int> q;

struct node{
    int next, v;
    LL dis;
}edge[maxn << 5];

void add(int u, int v, LL dis){
    edge[cnt].v = v;
    edge[cnt].next = head[u];
    edge[cnt].dis = dis;
    head[u] = cnt++;
}

bool bfs(){
    memset(dep, 0x7f, sizeof(dep));
    for(int i = 1; i <= n; i++) cur[i] = head[i];
    dep[s] = 0;
    q.push(s);
    while(!q.empty()){
        int now = q.front();
        q.pop();
        for(int k = head[now]; ~k; k = edge[k].next){
            int v = edge[k].v;
            if(dep[v] > inf && edge[k].dis){
                dep[v] = dep[now] + 1;
                q.push(v);
            }
        }
    }
    return dep[t] < inf;
}

LL dfs(int now, int limit){
    if(!limit || now == t) return limit;
    LL flow = 0, ins;
    for(int k = cur[now]; ~k; k = edge[k].next){
        cur[now] = k;
        int v = edge[k].v;
        if(dep[v] == dep[now] + 1 && (ins = dfs(v, min(LL(limit), edge[k].dis)))){
            flow += ins;
            limit -= ins;
            edge[k].dis -= ins;
            edge[k^1].dis += ins;
            if(!limit) break;
        }
    }
    return flow;
}

LL Dinic(){
    LL maxflow = 0;
    while(bfs())
        maxflow += dfs(s, inf);
    return maxflow;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    cin >> n >> m >> s >> t;
    memset(head, -1, sizeof(head));
    int u, v;
    LL c;
    for(int i = 1; i <= m; i++){
        cin >> u >> v >> c;
        add(u, v, c);
        add(v, u, 0);
    }
    cout << Dinic() << endl;
return 0;}

ISAP

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long LL;
const int maxn = 1e3 + 5;
const LL inf = 0x7fffffffffffffff;

int n, cnt;
int head[maxn], cur[maxn], dep[maxn], num[maxn], pre[maxn];
queue<int> q;

struct node{
    int next, v;
    LL dis;
}edge[maxn << 5];

void add(int u, int v, int dis){
    edge[cnt].v = v;
    edge[cnt].next = head[u];
    edge[cnt].dis = dis;
    head[u] = cnt++;
}

void bfs(int t){
    for(int i = 1; i <= n; i++){
        cur[i] = head[i];
        dep[i] = n;
    }
    dep[t] = 0;
    q.push(t);
    while(!q.empty()){
        int now = q.front();
        q.pop();
        for(int k = head[now]; ~k; k = edge[k].next){
            int v = edge[k].v;
            if(dep[v] == n && edge[k^1].dis){
                dep[v] = dep[now] + 1;
                q.push(v);
            }
        }
    }
}

LL add_flow(int s, int t){
    LL ans = inf;
    int u = t;
    while(u != s){
        ans = min(ans, edge[pre[u]].dis);
        u = edge[pre[u]^1].v;
    }
    u = t;
    while(u != s){
        edge[pre[u]].dis -= ans;
        edge[pre[u]^1].dis += ans;
        u = edge[pre[u]^1].v;
    }
    return ans;
}

LL ISAP(int s, int t){
    LL maxflow = 0;
    int u = s, v;
    bfs(t);
    for(int i = 1; i <= n; i++)
        num[dep[i]]++;
    while(dep[s] < n){
        if(u == t){
            maxflow += add_flow(s, t);
            u = s;
        }
        bool flag = false;
        for(int k = cur[u]; ~k; k = edge[k].next){
            cur[u] = k;
            v = edge[k].v;
            if(dep[u] == dep[v] + 1 && edge[k].dis){
                flag = true;
                u = v;
                pre[v] = k;
                break;
            }
        }
        if(!flag){
            int minn = n - 1;
            for(int k = head[u]; ~k; k = edge[k].next)
                if(edge[k].dis)
                    minn = min(minn, dep[edge[k].v]);
            if((--num[dep[u]]) == 0)break;
            num[dep[u] = minn + 1]++;
            cur[u] = head[u];
            if(u != s)
                u = edge[pre[u]^1].v;
        }
    }
    return maxflow;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int m, s, t;
    int u, v, c;
    memset(head, -1, sizeof(head));
    cin >> n >> m >> s >> t;
    for(int i = 1; i <= m; i++){
        cin >> u >> v >> c;
        add(u, v, c);
        add(v, u, 0);
    }
    cout << ISAP(s, t) << endl;
}

二分图

       最大独立集=节点数-最大匹配数

匈牙利

// 匈牙利算法 洛谷 P3386
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000005
struct node{
    int v, next;
}tree[maxn];

int cnt, head[1005], cx[1005], cy[1005];
bool vis[1005];

int dfs(int u){
    for(int k = head[u]; k; k = tree[k].next){
        int v = tree[k].v;
        if(!vis[v]){
            vis[v] = true;
            if(!cy[v] || dfs(cy[v])){
                cx[u] = v;
                cy[v] = u;
                return 1;
            }
        }
    }
    return 0;
}

int read(){
    char c = getchar();
    int f = 1, ans = 0;
    while(c < '0' || c > '9'){
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9'){
        ans = ans*10 + c - '0';
        c = getchar();
    }
    return ans*f;
}
int main(){
    int i, n, m, e, u, v, ans = 0;
    n = read(), m = read(), e = read();
    for(i = 1; i <= e; i++){
        u = read(), v = read();
        if(u > n || v > m) continue;
        tree[++cnt].v = v;
        tree[cnt].next = head[u];
        head[u] = cnt;
    }
    for(i = 1; i <= n; i++){
        if(head[i] && !cx[i]){
            memset(vis, 0, sizeof(vis));
            ans += dfs(i);
        }
    }
    printf("%d\n",ans);
return 0;}

HK算法

// hdu 6808
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long LL;
const int maxn = 2e5 + 5;
const int inf = 0x7fffffff;

int cnt, id, dis, num;
int head[maxn], xlink[maxn], ylink[maxn], dx[maxn], dy[maxn], idx[maxn];
unordered_map<int, int> xid, yid;
queue<int> q;

struct node{
    int next, v;
}edge[maxn << 5];

void add(int u, int v){
    edge[cnt].v = v;
    edge[cnt].next = head[u];
    head[u] = cnt++;
}

bool bfs(){
    bool flag = false;
    while(!q.empty())q.pop();
    for(int i = 1; i <= id; i++)
        dx[i] = dy[i] = -1;
    for(int i = 1; i <= num; i++){
        if(xlink[idx[i]] == -1){
            q.push(idx[i]);
            dx[idx[i]] = 0;
        }
    }
    while(!q.empty()){
        int u = q.front();
        q.pop();
        for(int k = head[u]; ~k; k = edge[k].next){
            int v = edge[k].v;
            if(~dy[v])continue;
            dy[v] = dx[u] + 1;
            if(~ylink[v]){
                dx[ylink[v]] = dy[v] + 1;
                q.push(ylink[v]);
            }else
                flag = true;
        }
    }
    return flag;
}

int dfs(int u){
    for(int k = head[u]; ~k; k = edge[k].next){
        int v = edge[k].v;
        if(dy[v] == dx[u] + 1){
            dy[v] = -2;
            if(ylink[v] == -1 || dfs(ylink[v])){
                xlink[u] = v;
                ylink[v] = u;
                return 1;
            }
        }
    }
    return 0;
}

int HK(){
    int ans = 0;
    while(bfs()){
        for(int i = 1; i <= num; i++){
            if(~xlink[idx[i]])continue;
            ans += dfs(idx[i]);
        }
    }
    return ans;
}

void init(int n){
    n *= 2;
    cnt = id = num = 0;
    xid.clear();
    yid.clear();
    for(int i = 1; i <= n; i++)
        head[i] = xlink[i] = ylink[i] = -1;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int T, n, u, v, x, y, ti;
    cin >> T;
    while(T--){
        cin >> n;
        init(n);
        for(int i = 1; i <= n; i++){
            cin >> x >> ti;
            y = x + ti;
            x = x - ti;
            if(!xid[x]){
                xid[x] = ++id;
                idx[++num] = id;
            }
            u = xid[x];
            if(!yid[y])
                yid[y] = ++id;
            v = yid[y];
            add(u, v);
        }
        cout << HK() << endl;
    }
}

LCA

// ST表版本 洛谷 P3379
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000005
int dp[maxn][(int)log2(maxn) + 2], dep[maxn<<1], fa[maxn], first[maxn], cnt, ver[maxn], tol;
int head[maxn];
int read(){
    char c = getchar();
    int f = 1, ans = 0;
    while(c < '0' || c > '9'){
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9'){
        ans = ans*10 + c - '0';
        c = getchar();
    }
    return ans*f;
}

struct node{
    int next, v;
}tree[maxn<<1];

void dfs(int v, int f, int d){
    first[v] = ++cnt;
    fa[v] = f;
    dep[cnt] = d;
    ver[cnt] = v;
    for(int k = head[v]; ~k; k = tree[k].next){
        if(tree[k].v == f) continue;
        dfs(tree[k].v, v, d + 1);
        dep[++cnt] = d;
        ver[cnt] = v;
    }
}
void ST(){
    for(int i = 1; i <= cnt; i++)
        dp[i][0] = i;
    for(int j = 1; (1<<j) <= cnt; j++){
        int s = 1<<j;
        for(int i = 1; i + s - 1 <= cnt; i++){
            int a = dp[i][j - 1], b = dp[i + (1<<(j-1))][j - 1];
            dp[i][j] = dep[a] < dep[b] ? a : b;
        }
    }
}

int RMQ(int x, int y){
    x = first[x], y = first[y];
    if(x > y) swap(x, y);
    int k = (int)floor(log2(y - x + 1));
    int a = dp[x][k], b = dp[y - (1<<k) + 1][k];
    return ver[dep[a] < dep[b] ? a : b];
}

void add(int x, int y){
    tree[++tol].v = y;
    tree[tol].next = head[x];
    head[x] = tol;
}

int main(){
    int x, y, m, n, root, i;
    n = read(), m = read(), root = read();
    memset(head, -1, sizeof(head));
    for(i = 1; i < n; i++){
        x = read(), y = read();
        add(x, y);
        add(y, x);
    }
    dfs(root, 0, 1);
    ST();
    for(i = 1; i <= m; i++){
        x = read(), y = read();
        printf("%d\n", RMQ(x,y));
    }
return 0;}

基尔霍夫矩阵求无向图生成树数量

// https://vjudge.net/problem/SPOJ-HIGH/origin
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long LL;
const int maxn = 1e2 + 5;
const LL mod = 998244353;
int n, m;
LL a[maxn][maxn], du[maxn];
LL det(){					
    LL ans = 1;
    for(int i = 2; i <= n; i++){		// 计算行列式从1开始
        for(int j = i + 1; j <= n; j++){
            while(a[j][i] != 0){
                LL u = a[i][i] / a[j][i];	// 逆元
                for(int k = i; k <= n; k++){
                    LL t = a[i][k] - a[j][k]*u; // % mod) + mod)%mod;
                    a[i][k] = a[j][k];
                    a[j][k] = t;
                }
                ans = -ans;
            }
        }
        ans = ans*a[i][i]; //%mod;
    }
    return abs(ans); // + mod)%mod;
}

int main(){
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
    int t, u, v;
    cin >> t;
    while(t--){
        cin >> n >> m;
        memset(du, 0, sizeof(du));
        memset(a, 0, sizeof(a));
        while(m--){
            cin >> u >> v;
            du[u]++;
            du[v]++;
            a[u][v] = a[v][u] -= 1;	// 边的数量
        }
        for(int i = 1; i <= n; i++)
            a[i][i] = du[i];
        cout << det() << endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值