【BUAA Spring Training 07】最大流 | 最小费用流 | 可行流 | 二分图 | H

    xiaoxiao2025-08-11  6

    第七场春训,谢谢szh、zkj学长 qwq! (补题式学习法)

    【BUAA Spring Training 07】

    Tags:最大流 费用流 可行流 二分图

    Problem A. Petya and Graph

    [A] 题意

    一个子图是由原图边的子集和点的子集构成的图(每条边的端点必须是点子集中的点)

    子图的权值总和定义为这个子图的边权和减去点权和。

    给定一个没有自环重边的无向图,求最大子图权值。点数边数都 ∈ [ 1 , 1 0 3 ] \in [1, 10^3] [1,103]

    [A] 思路

    看到这个范围就应该想到是网络流…

    我们把每条边视为一个中介点,那么问题就转换为了典型的最大权闭合子图。

    建图方式就是,原图每个结点以点权为容量连向超级汇,然后把每条边拆成一个中介点,从超级源拉一条容量为边权的弧过来,接着再把中介点和原边的两个端点以无穷容量连接就行了。

    然后把原图边权全部相加,再减去建图后的最大流就是答案。

    时间复杂度:网络流,你懂的, O ( O( O(能过 ) ) )

    [A] 代码

    #include <cstdio> #include <cstring> #include <limits> #define LL long long #define ULL unsigned LL #define _BS 1048576 char _bf[_BS]; char *__p1=_bf,*__p2=_bf; #define _IO char *_p1=__p1,*_p2=__p2; #define _OI __p1=_p1,__p2=_p2; #ifdef _KEVIN #define GC getchar() #else #define GC (_p1==_p2&&(_p2=(_p1=_bf)+fread(_bf,1,_BS,stdin),_p1==_p2)?EOF:*_p1++) #endif #define PC putchar #define _Q_(x) {register char _c=GC,_v=1;for(x=0;_c<48||_c>57;_c=GC)if(_c==45)_v=-1; #define _H_(x) for(;_c>=48&&_c<=57;x=(x<<1)+(x<<3)+_c-48,_c=GC);if(_v==-1)x=-x;} #define sc(x) _Q_(x)_H_(x) #define se(x) _Q_(x)else if(_c==EOF)return 0;_H_(x) #define _G1(_1) int _1;sc(_1) #define _G2(_1,_2) int _1,_2;sc(_1)sc(_2) #define _G3(_1,_2,_3) int _1,_2,_3;sc(_1)sc(_2)sc(_3) #define _gG(_1,_2,_3,_get, ...) _get #define get(...) _gG(__VA_ARGS__,_G3,_G2,_G1, ...)(__VA_ARGS__) #define _F0N(i,n) for(auto i=0;i<(n);++i) #define _FLR(i,l,r) for(auto i=(l);i<(r);++i) #define _gF(_1, _2, _3, _F, ...) _F #define F(...) _gF(__VA_ARGS__,_FLR,_F0N, ...)(__VA_ARGS__) #define _FD0(i,n) for(auto i=0;i<=(n);++i) #define _FDL(i,l,r) for(auto i=(l);i<=(r);++i) #define _gFD(_1, _2, _3, _FD, ...) _FD #define FD(...) _gFD(__VA_ARGS__,_FDL,_FD0, ...)(__VA_ARGS__) #define FRC(R,C) for(int r=0;r<R;++r)for(int c=0;c<C;++c) template<class T> void UPRT(const T _){if(_>=10)UPRT(_/10);PC(_%10+48);} #define UPL(_) UPRT(_),PC(10) template<class T> void PRT(const T _){if(_<0){PC(45),UPRT<ULL>(-(ULL)_);return;}if(_>=10)PRT(_/10);PC(_%10+48);} #define PL(_) PRT(_),PC(10) #define MAX(a, b) ((a)>(b)?(a):(b)) #define MIN(a, b) ((a)<(b)?(a):(b)) constexpr int MV(6e3+7), ME(MV<<1); template <typename cint> class Dinic { private: static constexpr cint CINT_MAX = std::numeric_limits<cint>::max(); struct Ed { int ne, u, v; cint c; } ed[ME]; int head[MV], cur[MV], tot; int V, S, T; int de[MV]; bool bfs() { static int q[MV]; int hd = 0, tl = 0; memset(de, 0, sizeof(*de) * (V+2)); de[q[tl++]=S] = 1; while (hd != tl) { const int u = q[hd++]; for (int i=head[u]; i; i=ed[i].ne) { const int v = ed[i].v; if (ed[i].c && !de[v]) { de[q[tl++]=v] = de[u] + 1; if (v == T) return true; } } } return false; } cint dfs(const int u, cint in) { if (u == T) return in; cint out = 0; for (int i=cur[u]; in&&(cur[u]=i); i=ed[i].ne) { if (ed[i].c>0 && de[ed[i].v]==de[u]+1) { const cint tp = dfs(ed[i].v, MIN(in, ed[i].c)); in -= tp, out += tp, ed[i].c -= tp, ed[i^1].c += tp; } } if (in || !out) de[u] = -1; return out; } public: void init(const int v) { if (V) memset(head, 0, sizeof(*head) * (V+2)); V = v; tot = 1; } void edd(const int u, const int v, const cint c = CINT_MAX) { ed[++tot].ne=head[u], ed[tot].u=u, ed[tot].v=v, ed[tot].c=c, head[u]=tot; ed[++tot].ne=head[v], ed[tot].u=v, ed[tot].v=u, ed[tot].c=0, head[v]=tot; } cint max_flow(const int s, const int t) { cint sum = 0; S = s, T = t; while (bfs()) { memcpy(cur, head, sizeof(*head) * (V+2)); sum += dfs(s, CINT_MAX); } return sum; } }; Dinic<LL> mf; int main() { _IO get(V, E); const int S = 0, T = V+E+1; mf.init(T-S+1); FD(i, 1, V) { get(ai) // cost mf.edd(i, T, ai); } LL sum = 0; FD(i, 1, E) { get(u, v, c) sum += c; mf.edd(V+i, u); mf.edd(V+i, v); mf.edd(S, V+i, c); } PL(sum - mf.max_flow(S, T)); #ifdef _KEVIN getchar(); #endif return 0; }

    Problem B. Scaygerboss

    (待更)

    最新回复(0)