题目链接:点击打开链接
题意:
给定n个带权点m条无向带权边
选一个子图。则这个子图的权值为 边权和-点权和
求一个最大的权值
把边也当成点。然后是最大权闭合图
dinic:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; //点标 从0開始 F.Init(n) n=最大点标+10 const int N = 200010; const int M = 500010; const int INF = ~0u >> 2; template<class T> struct Max_Flow { int n; int Q[N], sign; int head[N], level[N], cur[N], pre[N]; int nxt[M], pnt[M], E; T cap[M]; void Init(int n) { this->n = n; E = 0; std::fill(head, head + n, -1); } //有向rw 就= 0 void add(int from, int to, T c, T rw) { pnt[E] = to; cap[E] = c; nxt[E] = head[from]; head[from] = E++; pnt[E] = from; cap[E] = rw; nxt[E] = head[to]; head[to] = E++; } bool Bfs(int s, int t) { sign = t; std::fill(level, level + n, -1); int *front = Q, *tail = Q; *tail++ = t; level[t] = 0; while(front < tail && level[s] == -1) { int u = *front++; for(int e = head[u]; e != -1; e = nxt[e]) { if(cap[e ^ 1] > 0 && level[pnt[e]] < 0) { level[pnt[e]] = level[u] + 1; *tail ++ = pnt[e]; } } } return level[s] != -1; } void Push(int t, T &flow) { T mi = INF; int p = pre[t]; for(int p = pre[t]; p != -1; p = pre[pnt[p ^ 1]]) { mi = std::min(mi, cap[p]); } for(int p = pre[t]; p != -1; p = pre[pnt[p ^ 1]]) { cap[p] -= mi; if(!cap[p]) { sign = pnt[p ^ 1]; } cap[p ^ 1] += mi; } flow += mi; } void Dfs(int u, int t, T &flow) { if(u == t) { Push(t, flow); return ; } for(int &e = cur[u]; e != -1; e = nxt[e]) { if(cap[e] > 0 && level[u] - 1 == level[pnt[e]]) { pre[pnt[e]] = e; Dfs(pnt[e], t, flow); if(level[sign] > level[u]) { return ; } sign = t; } } } T Dinic(int s, int t) { pre[s] = -1; T flow = 0; while(Bfs(s, t)) { std::copy(head, head + n, cur); Dfs(s, t, flow); } return flow; } }; Max_Flow <int>F; int n, m; int work(){ F.Init(n+m+10); int from = 0, to = n + m +1, A; for(int i = 1; i <= n; i++){ scanf("%d", &A); F.add(i, to, A, 0); } int u, v, d, all = 0; for(int i = 1; i <= m; i++){ scanf("%d %d %d", &u, &v, &d); all += d; F.add(from, n+i, d, 0); F.add(n+i, u, INF, 0); F.add(n+i, v, INF, 0); } return all - F.Dinic(from, to); } int main(){ while(cin>>n>>m) cout<<work()<<endl; return 0; }
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<vector> using namespace std; #define ll int const int MAXN = 100010;//点数的最大值 const int MAXM = 400010;//边数的最大值 const int INF = 0x3f3f3f3f; struct Edge { int to,next,cap,flow; }edge[MAXM];//注意是MAXM int tol; int head[MAXN]; int gap[MAXN],dep[MAXN],cur[MAXN]; void add(int u,int v,int w,int rw = 0) { edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++; } int Q[MAXN]; void BFS(int start,int end) { memset(dep,-1,sizeof(dep)); memset(gap,0,sizeof(gap)); gap[0] = 1; int front = 0, rear = 0; dep[end] = 0; Q[rear++] = end; while(front != rear) { int u = Q[front++]; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(dep[v] != -1)continue; Q[rear++] = v; dep[v] = dep[u] + 1; gap[dep[v]]++; } } } int S[MAXN]; int sap(int start,int end,int N) { BFS(start,end); memcpy(cur,head,sizeof(head)); int top = 0; int u = start; int ans = 0; while(dep[start] < N) { if(u == end) { int Min = INF; int inser; for(int i = 0;i < top;i++) if(Min > edge[S[i]].cap - edge[S[i]].flow) { Min = edge[S[i]].cap - edge[S[i]].flow; inser = i; } for(int i = 0;i < top;i++) { edge[S[i]].flow += Min; edge[S[i]^1].flow -= Min; } ans += Min; top = inser; u = edge[S[top]^1].to; continue; } bool flag = false; int v; for(int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]) { flag = true; cur[u] = i; break; } } if(flag) { S[top++] = cur[u]; u = v; continue; } int Min = N; for(int i = head[u]; i != -1; i = edge[i].next) if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if(!gap[dep[u]])return ans; dep[u] = Min + 1; gap[dep[u]]++; if(u != start)u = edge[S[--top]^1].to; } return ans; } void init(){ tol = 0; memset(head,-1,sizeof(head)); } int n, m; ll work(){ init(); int from = 0, to = n + m +1, A; for(int i = 1; i <= n; i++){ scanf("%d", &A); add(i, to, A); } int u, v; ll d; ll all = 0; for(int i = 1; i <= m; i++){ scanf("%d %d %d", &u, &v, &d); all += d; add(from, n+i, d); add(n+i, u, INF); add(n+i, v, INF); } return all - sap(from, to,to+1); } int main(){ while(cin>>n>>m) cout<<work()<<endl; return 0; }