POI2005, Dicing
二分答案跑出是不是满流即可
#include <bits/stdc++.h>
using namespace std;
//using ll = long long;
#define int long long
const int V = 1010;
const int E = 101000;
template<typename T>
struct FlowGraph {
int s, t, vtot;
int h[V], idx;
int d[V], cur[V];
int e[E*2];
int ne[E*2];
int f[E*2];
void add(int a,int b,int c) {
e[idx]=b,f[idx]=c,ne[idx]=h[a],h[a]=idx++;
e[idx]=a,f[idx]=0,ne[idx]=h[b],h[b]=idx++;
}
bool bfs() {
for (int i = 1; i <= vtot; i++) {
d[i] = 0;
cur[i] = h[i];
}
queue<int> q;
q.push(s);
d[s] = 1;
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i =h[u]; ~i; i = ne[i]) {
int v=e[i];
if (f[i] && !d[v]) {
d[v] = d[u] + 1;
if (v == t) return true;
q.push(v);
}
}
}
return false;
}
T dfs(int u, T m) {
if (u == t) return m;
T flow = 0;
for (int i = cur[u]; ~i; cur[u] = i = ne[i])
if (f[i] && d[e[i]] == d[u] + 1) {
T t = dfs(e[i], min(m, f[i]));
f[i] -= t;
f[i ^ 1] += t;
m -= t;
flow += t;
if (!m) break;
}
if (!flow) d[u] = -1;
return flow;
}
T dinic() {
T flow=0;
while (bfs()) flow += dfs(s, numeric_limits<T>::max());
return flow;
}
void init(int s_, int t_, int vtot_) {
s = s_;
t = t_;
vtot = vtot_;
idx = 0;
for (int i = 1; i <= vtot; i++) h[i] = -1;
}
};
FlowGraph<int> g;
int n, m, s, t;
pair<int,int>q[10010];
bool check(int x) {
s=n+m+1;
t=n+m+2;
g.init(s,t,t);
for(int i=1; i<=m; i++) {
g.add(s,i,1);
g.add(i,m+q[i].first,1);
g.add(i,m+q[i].second,1);
}
for(int i=1; i<=n; i++) {
g.add(i+m,t,x);
}
return g.dinic()==m;
}
signed main() {
cin>>n>>m;
for(int i=1; i<=m; i++) {
cin>>q[i].first>>q[i].second;
}
int l=0,r=m;
while(l<=r) {
int mid=(l+r)>>1;
if(check(mid))r=mid-1;
else l=mid+1;
}
cout<<r+1<<endl;
}
bzoj 最小生成树(最小割模板)
#include <bits/stdc++.h>
using namespace std;
//using ll = long long;
#define int long long
const int V = 20010;
const int E = 201000;
template<typename T>
struct FlowGraph {
int s, t, vtot;
int h[V], idx;
int d[V], cur[V];
int e[E*2];
int ne[E*2];
int f[E*2];
/*struct edge {
int v, nxt;
T f;
} e[E * 2];
void addedge(int u,int v, T f){
e[etot]= {v, head[u], f}; head[u] = etot++;
e[etot]= {u, head[v], 0}; head[v] = etot++;
}*/
void add(int a,int b,int c,int d) {
e[idx]=b,f[idx]=c,ne[idx]=h[a],h[a]=idx++;
e[idx]=a,f[idx]=d,ne[idx]=h[b],h[b]=idx++;
}
bool bfs() {
for (int i = 1; i <= vtot; i++) {
d[i] = 0;
cur[i] = h[i];
}
queue<int> q;
q.push(s);
d[s] = 1;
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i =h[u]; ~i; i = ne[i]) {
int v=e[i];
if (f[i] && !d[v]) {
d[v] = d[u] + 1;
if (v == t) return true;
q.push(v);
}
}
}
return false;
}
/* T dfs(int u, T m) {
if (u == t) return m;
T flow = 0;
for (int i = cur[u]; ~i; cur[u] = i = ne[i]){
int v=e[i];
if (f[i] && d[v] == d[u] + 1) {
T t = dfs(v, min(m-flow, f[i]));
if(!t)d[v]=-1;
f[i] -= t;
f[i ^ 1] += t;
flow+=t;
}
}
return flow;
}*/
T dfs(int u, T m) {
if (u == t) return m;
T flow = 0;
for (int i = cur[u]; ~i; cur[u] = i = ne[i])
if (f[i] && d[e[i]] == d[u] + 1) {
T t = dfs(e[i], min(m, f[i]));
f[i] -= t;
f[i ^ 1] += t;
m -= t;
flow += t;
if (!m) break;
}
if (!flow) d[u] = -1;
return flow;
}
T dinic() {
T flow=0;
while (bfs()) flow += dfs(s, numeric_limits<T>::max());
return flow;
}
void init(int s_, int t_, int vtot_) {
s = s_;
t = t_;
vtot = vtot_;
idx = 0;
for (int i = 1; i <= vtot; i++) h[i] = -1;
}
};
FlowGraph<int> g;
int n, m, s, t, k;
array<int, 3> e[E];
signed main() {
cin>>n>>m;
for(int i=1; i<=m; i++) {
int a,b,c;
cin>>a>>b>>c;
e[i]= {a,b,c};
}
cin>>s>>t>>k;
g.init(s,t,n);
for(int i=1; i<=m; i++) {
if(e[i][2]<k)g.add(e[i][0],e[i][1],1,1);
}
int ans1=g.dinic();
g.init(s, t, n);
for(int i=1; i<=m; i++) {
if(e[i][2]>k)g.add(e[i][0],e[i][1],1,1);
}
cout<<ans1+g.dinic()<<endl;
}
拆点求最小割
//#include <bits/stdc++.h>
#include <iostream>
#include <cstring>
#include <queue>
#include <cmath>
#include <limits>
using namespace std;
//using ll = long long;
#define int long long
const int V = 1010;
const int E = 101000;
template<typename T>
struct FlowGraph {
int s, t, vtot;
int h[V], idx;
int d[V], cur[V];
int e[E*2];
int ne[E*2];
int f[E*2];
/*struct edge {
int v, nxt;
T f;
} e[E * 2];
void addedge(int u,int v, T f){
e[etot]= {v, head[u], f}; head[u] = etot++;
e[etot]= {u, head[v], 0}; head[v] = etot++;
}*/
void add(int a,int b,int c) {
e[idx]=b,f[idx]=c,ne[idx]=h[a],h[a]=idx++;
e[idx]=a,f[idx]=0,ne[idx]=h[b],h[b]=idx++;
}
bool bfs() {
for (int i = 1; i <= vtot; i++) {
d[i] = 0;
cur[i] = h[i];
}
queue<int> q;
q.push(s);
d[s] = 1;
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i =h[u]; ~i; i = ne[i]) {
int v=e[i];
if (f[i] && !d[v]) {
d[v] = d[u] + 1;
if (v == t) return true;
q.push(v);
}
}
}
return false;
}
/* T dfs(int u, T m) {
if (u == t) return m;
T flow = 0;
for (int i = cur[u]; ~i; cur[u] = i = ne[i]){
int v=e[i];
if (f[i] && d[v] == d[u] + 1) {
T t = dfs(v, min(m-flow, f[i]));
if(!t)d[v]=-1;
f[i] -= t;
f[i ^ 1] += t;
flow+=t;
}
}
return flow;
}*/
T dfs(int u, T m) {
if (u == t) return m;
T flow = 0;
for (int i = cur[u]; ~i; cur[u] = i = ne[i])
if (f[i] && d[e[i]] == d[u] + 1) {
T t = dfs(e[i], min(m, f[i]));
f[i] -= t;
f[i ^ 1] += t;
m -= t;
flow += t;
if (!m) break;
}
if (!flow) d[u] = -1;
return flow;
}
T dinic() {
T flow=0;
while (bfs()) flow += dfs(s, numeric_limits<T>::max());
return flow;
}
void init(int s_, int t_, int vtot_) {
s = s_;
t = t_;
vtot = vtot_;
idx = 0;
for (int i = 1; i <= vtot; i++) h[i] = -1;
}
int st[V];
// memset(st,0,sizeof(st));
void dfs(int u) {
st[u]=1;
for(int i=h[u]; ~i; i=ne[i]) {
if(f[i]&&!st[e[i]])
dfs(e[i]);
}
}
};
int inf =(int)1<<60;
FlowGraph<int> g;
int n, m;
signed main() {
cin>>n>>m;
g.init(2,2*n-1,2*n);
for(int i=1; i<=m; i++) {
int a,b;
cin>>a>>b;
g.add(2*a,2*b-1,inf);
g.add(2*b,2*a-1,inf);
}
for(int i=1; i<=n; i++) {
int x;
cin>>x;
g.add(2*i-1,2*i,x);
}
cout<<g.dinic()<<endl;
g.dfs(2);
vector<int>ans;
for(int i=2; i<n; i++) {
if(g.st[2*i-1]&&!g.st[2*i]) {
ans.push_back(i);
}
}
/* for(int i=1;i<n;i++){
cout<<g.st[2*i-1]<<" "<<g.st[2*i]<<endl;
}*/
cout<<ans.size()<<endl;
for(auto x:ans)cout<<x<<" ";
cout<<endl;
}
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int V = 20100;
const int E = 201000;
template<typename T>
struct MinCostGraph {
int s, t, vtot;
int h[V], idx;
T d[V], flow, cost;
int pre[V];
bool vis[V];
int f[E*2];
int w[E*2];
int e[E*2];
int ne[E*2];
/* struct edge {
int v, nxt;
T f, c;
} e[E * 2];
/*void addedge(int u,int v, T f, T c, T f2 = 0) {
e[etot]= {v, head[u], f, c};
head[u] = etot++;
e[etot]= {u, head[v], f2, -c};
head[v] = etot++;
}*/
void add(int a, int b, int c, int d) {
e[idx] = b, f[idx] = c, w[idx] = d, ne[idx] = h[a], h[a] = idx ++ ;
e[idx] = a, f[idx] = 0, w[idx] = -d, ne[idx] = h[b], h[b] = idx ++ ;
}
bool spfa() {
T inf = numeric_limits<T>::max() / 2;
for (int i = 1; i <= vtot; i++) {
d[i] = inf;
vis[i] = false;
pre[i] = -1;
}
d[s] = 0;
vis[s] = true;
queue<int> q;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
vis[u] = false;
for(int i=h[u]; ~i; i=ne[i]) {
int v = e[i];
if (f[i] && d[v] > d[u] + w[i]) {
d[v] = d[u] + w[i];
pre[v] = i;
if (!vis[v]) {
vis[v] = 1;
q.push(v);
}
}
}
}
return d[t] != inf;
}
void augment() {
int u = t;
T q = numeric_limits<T>::max();
while (~pre[u]) {
q = min(q, f[pre[u]]);
u = e[pre[u] ^ 1];
}
flow += q;
cost += q * d[t];
u = t;
while (~pre[u]) {
f[pre[u]] -= q;
f[pre[u] ^ 1] += q;
u = e[pre[u] ^ 1];
}
}
pair<T, T> solve() {
flow = 0;
cost = 0;
while (spfa()) augment();
return {flow, cost};
}
void init(int s_, int t_, int vtot_) {
s = s_;
t = t_;
vtot = vtot_;
idx = 0;
for (int i = 1; i <= vtot; i++) h[i] = -1;
}
};
MinCostGraph<int> g1,g2;
int n, m;
int main() {
cin>>n>>m;
g1.init(n+m+1,n+m+2,n+m+2);
g2.init(n+m+1,n+m+2,n+m+2);
for(int i=1; i<=n; i++) {
int x;
cin>>x;
g1.add(n+m+1,i,x,0);
g2.add(n+m+1,i,x,0);
}
for(int i=1; i<=m; i++) {
int x;
cin>>x;
g1.add(i+n,n+m+2,x,0);
g2.add(i+n,n+m+2,x,0);
}
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
int x;
cin>>x;
g1.add(i,j+n,1<<30,x);
g2.add(i,j+n,1<<30,-x);
}
}
pair<int,int>t1=g1.solve();
pair<int,int>t2=g2.solve();
cout<<t1.second<<endl;
cout<<t2.second*(-1)<<endl;
}