最小费用最大流
// 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;
}
}