1. 程式人生 > >[TJOI2015]線性代數(網絡流)

[TJOI2015]線性代數(網絡流)

() esp tail max main 並且 clu lock set

[TJOI2015]線性代數(最大權閉合子圖,網絡流)

為了提高智商,ZJY開始學習線性代數。她的小夥伴菠蘿給她出了這樣一個問題:給定一個n*n的矩陣B和一個1×n的矩陣C。求出一個1×n的01矩陣A。使得\(D=(A×B?C)×A^T\)最大,其中 \(A^T\) 為A的轉置。輸出D。

這相當於:若同時選擇X和Y,獲得\(B[x][y]\)收益,若選擇了X,需要\(C[x]\)的代價。然後,仿效前面那道題的做法,這道題目就是一個最大閉合權子圖(滿足用割選擇一些點,並且有些點必選的條件)。

#include <cstdio> 
#include <cstring>
using
namespace std; const int maxn=3e5+5, maxm=1e6+5, INF=1e9; int n, m, src, dst, ans; inline int min(int x, int y){ return x<y?x:y; } struct Edge{ int to, nxt, f; }e[maxm*2]; int fir[maxn], cnte=1; void addedge(int x, int y, int v){ Edge &ed=e[++cnte]; ed.to=y; ed.nxt=fir[x]; ed.f=v; fir[x]=cnte; } int
q[maxn], head, tail, dep[maxn]; bool bfs(){ memset(dep, 0, sizeof(dep)); dep[src]=1; head=tail=0; q[tail++]=src; int u; while (head<tail){ u=q[head++]; for (int i=fir[u]; ~i; i=e[i].nxt) if (e[i].f&&!dep[e[i].to]){ dep[e[i].to]=dep[u]+1
; q[tail++]=e[i].to; } } return dep[dst]; } int cur[maxn]; int dfs(int u, int flow){ if (u==dst) return flow; for (int i=cur[u]; ~i; i=e[i].nxt, cur[u]=i) if (dep[e[i].to]==dep[u]+1&&e[i].f){ int minm=dfs(e[i].to, min(flow, e[i].f)); e[i].f-=minm; e[i^1].f+=minm; if (minm) return minm; } return 0; } int Dinic(){ int ans=0, t; while (bfs()){ memcpy(cur, fir, sizeof(fir)); while (t=dfs(src, INF)) ans+=t; } return ans; } int main(){ memset(fir, -1, sizeof(fir)); scanf("%d", &n); int t; src=0; dst=n*(n+1)+1; for (int i=1; i<=n; ++i) for (int j=1; j<=n; ++j){ scanf("%d", &t); ans+=t; addedge(src, i*n+j, t); addedge(i*n+j, src, 0); addedge(i*n+j, i, INF); addedge(i, i*n+j, 0); addedge(i*n+j, j, INF); addedge(j, i*n+j, 0); } for (int i=1; i<=n; ++i){ scanf("%d", &t); addedge(i, dst, t); addedge(dst, i, 0); } ans-=Dinic(); printf("%d\n", ans); return 0; }

[TJOI2015]線性代數(網絡流)