/** 题目:hdu3879 Base Station 最大权闭合子图 边权有正有负 链接:http://acm.hdu.edu.cn/showproblem.php?pid=3879 题意:给出n个地方可以建房子,给出每个地方建房子的费用,如果A,B两个地方建了房子,那么可以获得C的利润。 求建一些房子可以获得的最大利润。 思路:最大权闭合子图。 n个房子与t相连,容量为费用。如果A,B两个地方建了房子,那么可以获得利润C。可以新增一个点x,s->x,cap=C; x->a,cap=INF; x->b,cap=INF; 不懂可以先看这题:http://www.cnblogs.com/xiaochaoqun/p/7227268.html 求s-t最大流,结果为所有正价值之和-最大流。 或者: 求s-t最大流之后,此时dinic的vis为1的点表示在该最小割的S集合内。S集合除去s点的其他点就是需要裁员的人,从中可以获取人数,以及计算价值和。 */ #include<iostream> #include<cstring> #include<vector> #include<map> #include<cstdio> #include<sstream> #include<algorithm> #include<queue> using namespace std; typedef long long LL; const int INF = 0x3f3f3f3f; const int N = 55005; struct Edge{ int from, to, cap, flow; Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){} }; struct Dinic{ int n, m, s, t; vector<Edge> edges; vector<int> G[N]; bool vis[N]; LL d[N]; int cur[N]; void init(int n) { this->n = n; for(int i = 0; i <= n; i++) G[i].clear(); edges.clear(); } void AddEdge(int from,int to,int cap) { edges.push_back(Edge(from,to,cap,0)); edges.push_back(Edge(to,from,0,0)); m = edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BFS(){ memset(vis, 0, sizeof vis); queue<int> Q; Q.push(s); d[s] = 0; vis[s] = 1; while(!Q.empty()){ int x = Q.front(); Q.pop(); for(int i = 0; i < G[x].size(); i++){ Edge &e = edges[G[x][i]]; if(!vis[e.to]&&e.cap>e.flow){ vis[e.to] = 1; d[e.to] = d[x]+1; Q.push(e.to); } } } return vis[t]; } LL DFS(int x,LL a){ if(x==t||a==0) return a; LL flow = 0, f; for(int &i = cur[x]; i < G[x].size(); i++){ Edge& e = edges[G[x][i]]; if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,(LL)e.cap-e.flow)))>0){ e.flow += f; edges[G[x][i]^1].flow -= f; flow += f; a -= f; if(a==0) break; } } return flow; } LL Maxflow(int s,int t){ this->s = s, this->t = t; LL flow = 0; while(BFS()){ memset(cur, 0, sizeof cur); flow += DFS(s,INF); } return flow; } }; int main() { int n, m; while(scanf("%d%d",&n,&m)==2) { int s = 0, t = n+1+m; Dinic dinic; dinic.init(t); int w; for(int i = 1; i <= n; i++){ scanf("%d",&w); dinic.AddEdge(i,t,w); } int u, v; LL sum = 0; for(int i = 1; i <= m; i++){ scanf("%d%d%d",&u,&v,&w); dinic.AddEdge(s,i+n,w); dinic.AddEdge(i+n,u,INF); dinic.AddEdge(i+n,v,INF); sum += w; } printf("%lld ",sum-dinic.Maxflow(s,t)); } return 0; }