论文链接
#include "bits/stdc++.h"
#define hhh cerr<<"hhh"<
#define see(x) cerr<<(#x)<<'='<<(x)<
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {
int x=0,f=1;char c=getchar();while(c!='-'&&(c<'0'||c>'9'))c=getchar();if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}
const int maxn = 1e5+7;
const int maxm = 3e5+7;
const int inf = 0x3f3f3f3f;
int head[maxn], to[maxm], w[maxm], nxt[maxm], tot=1;
int cur[maxn], level[maxn];
void add_edge(int u, int v, int c) {
++tot; to[tot]=v; w[tot]=c; nxt[tot]=head[u]; head[u]=tot;
++tot; to[tot]=u; w[tot]=0; nxt[tot]=head[v]; head[v]=tot;
}
bool bfs(int s, int t) {
memset(level,0,sizeof(level));
queue<int> q;
level[s]=1;
q.push(s);
while(!q.empty()) {
int u=q.front(); q.pop();
for(int i=head[u]; i; i=nxt[i]) {
int v=to[i];
if(!w[i]||level[v]) continue;
level[v]=level[u]+1;
q.push(v);
}
}
return level[t];
}
int dfs(int u, int t, int flow) {
if(u==t||flow==0) return flow;
int f, ret=0;
for(int &i=cur[u]; i; i=nxt[i]) {
int v=to[i];
if(level[v]==level[u]+1&&(f=dfs(v,t,min(flow,w[i])))>0) {
w[i]-=f; w[i^1]+=f;
flow-=f; ret+=f;
if(!flow)break;
}
}
if(!ret) level[u]=0;
return ret;
}
int dinic(int s, int t) {
int ret=0;
while(bfs(s,t)) memcpy(cur,head,sizeof(cur)), ret+=dfs(s,t,inf);
return ret;
}
int main() {
int n=read(), m=read(), s=read(), t=read();
for(int i=1; i<=m; ++i) {
int u=read(), v=read(), w=read();
add_edge(u,v,w);
}
printf("%d\n", dinic(s,t));
}
#include "bits/stdc++.h"
#define hhh cerr<<"hhh"<
#define see(x) cerr<<(#x)<<'='<<(x)<
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {
int x=0,f=1;char c=getchar();while(c!='-'&&(c<'0'||c>'9'))c=getchar();if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}
const int maxn = 1e5+7;
const int maxm = 3e5+7;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
int head[maxn], to[maxm], nxt[maxm], tot=1;
double w[maxm];
int cur[maxn], level[maxn];
void add_edge(int u, int v, double c) {
++tot; to[tot]=v; w[tot]=c; nxt[tot]=head[u]; head[u]=tot;
++tot; to[tot]=u; w[tot]=0; nxt[tot]=head[v]; head[v]=tot;
}
bool bfs(int s, int t) {
memset(level,0,sizeof(level));
queue<int> q;
level[s]=1;
q.push(s);
while(!q.empty()) {
int u=q.front(); q.pop();
for(int i=head[u]; i; i=nxt[i]) {
int v=to[i];
if(fabs(w[i])<=eps||level[v]) continue;
level[v]=level[u]+1;
q.push(v);
}
}
return level[t];
}
double dfs(int u, int t, double flow) {
if(u==t||fabs(flow)==0) return flow;
double f, ret=0;
for(int &i=cur[u]; i; i=nxt[i]) {
int v=to[i];
if(level[v]==level[u]+1&&(f=dfs(v,t,min(flow,w[i])))>=eps) {
w[i]-=f; w[i^1]+=f;
flow-=f; ret+=f;
if(fabs(flow)<=eps)break;
}
}
if(fabs(ret)<=eps) level[u]=0;
return ret;
}
double dinic(int s, int t) {
double ret=0;
while(bfs(s,t)) memcpy(cur,head,sizeof(cur)), ret+=dfs(s,t,5e18);
return ret;
}
int main() {
int n=read(), m=read(), s=read(), t=read();
for(int i=1; i<=m; ++i) {
int u=read(), v=read();
double w; scanf("%lf", &w);
add_edge(u,v,w);
}
printf("%.3f\n", dinic(s,t));
}
#include "bits/stdc++.h"
#define hhh cerr<<"hhh"<
#define see(x) cerr<<(#x)<<'='<<(x)<
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {
int x=0,f=1;char c=getchar();while(c!='-'&&(c<'0'||c>'9'))c=getchar();if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}
const int maxn = 2e4+7;
const int maxm = 2e5+7;
const int inf = 0x3f3f3f3f;
ll maxflow, mincost;
int last[maxn], pre[maxn], dis[maxn], now[maxn];
int head[maxn], to[maxm], flow[maxm], cost[maxm], nxt[maxm], tot=1;
bool inq[maxn];
void add_edge(int u,int v,int f,int c) {
++tot; to[tot]=v; flow[tot]=f; cost[tot]=c; nxt[tot]=head[u]; head[u]=tot;
++tot; to[tot]=u; flow[tot]=0; cost[tot]=-c; nxt[tot]=head[v]; head[v]=tot;
}
void init() {
tot=1; memset(head,0,sizeof(head)); mincost=maxflow=0; }
bool spfa(int s, int t) {
memset(dis,inf,sizeof(dis));
memset(now,inf,sizeof(now));
memset(inq,0,sizeof(inq));
queue<int> q;
dis[s]=0; pre[t]=-1; q.push(s); inq[s]=1;
while(!q.empty()) {
int u=q.front(); q.pop(); inq[u]=0;
for(int i=head[u]; i; i=nxt[i]) {
int v=to[i];
if(flow[i]>0&&dis[v]>dis[u]+cost[i]) {
dis[v]=dis[u]+cost[i];
now[v]=min(now[u],flow[i]);
last[v]=i; pre[v]=u;
if(!inq[v]) q.push(v), inq[v]=1;
}
}
}
return pre[t]!=-1;
}
void MCMF(int s, int t) {
while(spfa(s,t)) {
int u=t;
maxflow+=now[t];
mincost+=now[t]*ll(dis[t]);
while(u!=s) {
flow[last[u]]-=now[t];
flow[last[u]^1]+=now[t];
u=pre[u];
}
}
}
int main() {
int n=read(), m=read(), s=read(), t=read();
for(int i=1; i<=m; ++i) {
int u=read(), v=read(), w=read(), f=read();
add_edge(u,v,w,f);
}
MCMF(s,t);
printf("%lld %lld\n", maxflow, mincost);
}
闭合图(针对有向图):图中点集的出边也在点集中。(相当于有向边终点是有向边起点的必要条件)
最大权闭合子图:图中每个点有点权,则权值最大的闭合子图为最大权闭合子图。
原闭合图构造:额外加入源点 s s s ,汇点 t t t ,与 s s s 相连的点( S S S )的点权都为正,与 t t t 相连的点( T T T )的点权都为负(0就随意啦),这两者的边权用点权(取绝对值)代替; S S S 与 T T T 的连边边权为无穷。
最大权闭合子图权值为: ∑ S − W \displaystyle \sum{S}-W ∑S−W( W W W为闭合图的最小割 )
(由于 < S , T > <S,T> 都是无穷边,因此最小割一定是简单割,即所有割边都与源点或汇点相连)