1497: [NOI2006]最大获利
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 6077 Solved: 2904
[Submit][Status][Discuss]
Description
新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战。THU集团旗下的CS&T通讯公司在新一代通讯技术血战的前夜,需要做太多的准备工作,仅就站址选择一项,就需要完成前期市场研究、站址勘测、最优化等项目。在前期市场调查和站址勘测之后,公司得到了一共N个可以作为通讯信号中转站的地址,而由于这些地址的地理位置差异,在不同的地方建造通讯中转站需要投入的成本也是不一样的,所幸在前期调查之后这些都是已知数据:建立第i个通讯中转站需要的成本为Pi(1≤i≤N)。另外公司调查得出了所有期望中的用户群,一共M个。关于第i个用户群的信息概括为Ai, Bi和Ci:这些用户会使用中转站Ai和中转站Bi进行通讯,公司可以获益Ci。(1≤i≤M, 1≤Ai, Bi≤N) THU集团的CS&T公司可以有选择的建立一些中转站(投入成本),为一些用户提供服务并获得收益(获益之和)。那么如何选择最终建立的中转站才能让公司的净获利最大呢?(净获利 = 获益之和 - 投入成本之和)
Input
输入文件中第一行有两个正整数N和M 。第二行中有N个整数描述每一个通讯中转站的建立成本,依次为P1, P2, …, PN 。以下M行,第(i + 2)行的三个数Ai, Bi和Ci描述第i个用户群的信息。所有变量的含义可以参见题目描述。
Output
你的程序只要向输出文件输出一个整数,表示公司可以得到的最大净获利。
Sample Input
1 2 3 4 5
1 2 3
2 3 4
1 3 3
1 4 2
4 5 3
Sample Output
HINT
【样例说明】选择建立1、2、3号中转站,则需要投入成本6,获利为10,因此得到最大收益4。【评分方法】本题没有部分分,你的程序的输出只有和我们的答案完全一致才能获得满分,否则不得分。【数据规模和约定】 80%的数据中:N≤200,M≤1 000。 100%的数据中:N≤5 000,M≤50 000,0≤Ci≤100,0≤Pi≤100。
Source
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <iostream> #include <cstring> #include <set> #include <queue> #include <algorithm> #include <vector> #include <map> #include <cctype> #include <cmath> #include <stack> #include <sstream> #include <list> #include <assert.h> #include <bitset> #include <numeric> #define debug() puts("++++") #define gcd(a, b) __gcd(a, b) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define fi first #define se second #define pb push_back #define sqr(x) ((x)*(x)) #define ms(a,b) memset(a, b, sizeof a) #define sz size() #define pu push_up #define pd push_down #define cl clear() //#define all 1,n,1 #define FOR(i,x,n) for(int i = (x); i < (n); ++i) #define freopenr freopen("in.txt", "r", stdin) #define freopenw freopen("out.txt", "w", stdout) using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int, int> P; const int INF = 0x3f3f3f3f; const LL LNF = 1e17; const double inf = 1e20; const double PI = acos(-1.0); const double eps = 1e-8; const int maxn = 55000 + 10; const int maxm = 3e5 + 10; const int mod = 1e9 + 7; const int dr[] = {-1, 0, 1, 0}; const int dc[] = {0, -1, 0, 1}; const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"}; int n, m; const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; inline bool is_in(int r, int c) { return r >= 0 && r < n && c >= 0 && c < m; } struct Edge{ int from, to, cap, flow; }; struct Dinic{ int n, m, s, t; vector<Edge> edges; vector<int> G[maxn]; bool vis[maxn]; int d[maxn]; int cur[maxn]; void init(int n){ this->n = n; for(int i = 0; i < n; ++i) G[i].cl; edges.cl; } void addEdge(int from, int to, int cap){ edges.pb((Edge){from, to, cap, 0}); edges.pb((Edge){to, from, 0, 0}); m = edges.sz; G[from].pb(m - 2); G[to].pb(m - 1); } bool bfs(){ queue<int> q; ms(vis, 0); q.push(s); d[s] = 0; vis[s] = 1; while(!q.empty()){ int u = q.front(); q.pop(); for(int i = 0; i < G[u].sz; ++i){ Edge &e = edges[G[u][i]]; if(!vis[e.to] && e.cap > e.flow){ vis[e.to] = 1; d[e.to] = d[u] + 1; q.push(e.to); } } } return vis[t]; } int dfs(int u, int a){ if(u == t || a == 0) return a; int flow = 0, f = 0; for(int &i = cur[u]; i < G[u].sz; ++i){ Edge &e = edges[G[u][i]]; if(d[e.to] == d[u] + 1 && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0){ e.flow += f; edges[G[u][i]^1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow; } int maxflow(int s, int t){ this->s = s; this->t = t; int flow = 0; while(bfs()){ ms(cur, 0); flow += dfs(s, INF); } return flow; } }; Dinic dinic; int main(){ scanf("%d %d", &n, &m); int ans = 0, s = 0, t = n + m + 1; for(int i = 1; i <= n; ++i){ int x; scanf("%d", &x); dinic.addEdge(s, i, x); } for(int i = 1; i <= m; ++i){ int a, b, c; scanf("%d %d %d", &a, &b, &c); dinic.addEdge(a, i + n, INF); dinic.addEdge(b, i + n, INF); dinic.addEdge(i + n, t, c); ans += c; } ans -= dinic.maxflow(s, t); printf("%d\n", ans); return 0; }