Base Station
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 65768/32768 K (Java/Others)Total Submission(s): 1965 Accepted Submission(s): 831
Problem Description
A famous mobile communication company is planning to build a new set of base stations. According to the previous investigation, n places are chosen as the possible new locations to build those new stations. However, the condition of each position varies much, so the costs to built a station at different places are different. The cost to build a new station at the ith place is P
i (1<=i<=n).
When complete building, two places which both have stations can communicate with each other.
Besides, according to the marketing department, the company has received m requirements. The ith requirement is represented by three integers A i, B i and C i, which means if place A i and B i can communicate with each other, the company will get C i profit.
Now, the company wants to maximize the profits, so maybe just part of the possible locations will be chosen to build new stations. The boss wants to know the maximum profits.
When complete building, two places which both have stations can communicate with each other.
Besides, according to the marketing department, the company has received m requirements. The ith requirement is represented by three integers A i, B i and C i, which means if place A i and B i can communicate with each other, the company will get C i profit.
Now, the company wants to maximize the profits, so maybe just part of the possible locations will be chosen to build new stations. The boss wants to know the maximum profits.
Input
Multiple test cases (no more than 20), for each test case:
The first line has two integers n (0<n<=5000) and m (0<m<=50000).
The second line has n integers, P1 through Pn, describes the cost of each location.
Next m line, each line contains three integers, A i, B i and C i, describes the ith requirement.
The first line has two integers n (0<n<=5000) and m (0<m<=50000).
The second line has n integers, P1 through Pn, describes the cost of each location.
Next m line, each line contains three integers, A i, B i and C i, describes the ith requirement.
Output
One integer each case, the maximum profit of the company.
Sample Input
5 5 1 2 3 4 5 1 2 3 2 3 4 1 3 3 1 4 2 4 5 3
Sample Output
4
Author
liulibo
Source
Recommend
这个问题要求的是建基站最大的收益,对应到最小割就应该转换成求解最小成本建站的问题,并将成本对应为图中边的容量。
将要建站的集合记为S,不建站的集合记为T。考虑s-t割,第i个基站建站成本为p[i],建站(属于S集合)则对应一条从第i个点到t点,容量为p[i]的边,不建站(属于T集合)则对应一条从s到i容量为0的边(也就是不连)。
对于a点和b点都建站有收益c,收益c就是成本为-c,但是网络流不适用于有负边的情况,所以要进行适当的转换。将情况反转过过来,一开始就当a和b的都建站有收益c,那么条件在图中就变成了如果他们没有都建站则成本要加上c(即减回收益c),这样边容量就转换成正的。一开记录下所有的收益和sum,最后求出sum-最小成本就是最大收益。所以对于条件(a,b,c),增加一个新节点n,连接s到n容量为c,连接n到a和b各一条容量为inf的边。这样连是因为要考虑,只有a不建站,只有b不建站,a和b都不建站的情况,画个图就容易理解了。
建完图后O(n^2m)的Dinic算法600ms就能过了。这个复杂度其实是上界而已,实际情况中一般不会达到,并且这道题中的图是稀疏图。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
#define maxn 5005
#define maxm 50005
#define inf 0x3f3f3f3f
int n,m;
int s,t;
struct edge
{
int to,cap,rev;
edge(int a, int b, int c){to=a;cap=b;rev=c;}
};
vector<edge> g[maxn+maxm];
void add(int u, int v, int cap)
{
g[u].push_back(edge(v,cap,g[v].size()));
g[v].push_back(edge(u,0,g[u].size()-1));
}
int level[maxn+maxm];
int itr[maxn+maxm];
void bfs()
{
queue<int> q;
while(!q.empty()) q.pop();
memset(level, -1, sizeof(level));
q.push(s);
level[s] = 0;
while(!q.empty()){
int u = q.front(); q.pop();
int v,w;
for(int i = 0; i < g[u].size(); i++){
v = g[u][i].to, w = g[u][i].cap;
if(level[v]!=-1 || w <= 0) continue;
level[v] = level[u]+1;
q.push(v);
if(v == t) return;
}
}
}
int dfs(int u, int f)
{
if(u == t) return f;
for(int &i = itr[u]; i < g[u].size(); i++){
int v = g[u][i].to, &w = g[u][i].cap, rev = g[u][i].rev;
if(level[v] != level[u]+1 || w <= 0) continue;
int d;
if(d=dfs(v, min(f,w))){
w -= d;
g[v][rev].cap += d;
return d;
}
}
return 0;
}
long long Dinic()
{
long long ret = 0;
while(1){
bfs();
if(level[t] == -1) break;
memset(itr, 0, sizeof(itr));
int f;
while((f = dfs(s, inf))){ret+= f;}
}
return ret;
}
int main()
{
while(scanf("%d%d", &n, &m)==2){
for(int i = 0; i < maxm+maxn; i++) g[i].clear();
s = 0; t = n+1;
int a,b,c;
for(int i = 1; i <= n; i++){
scanf("%d", &a);
add(i, t, a);
}
long long ans = 0;
for(int i = 1; i <= m; i++){
scanf("%d%d%d", &a, &b, &c);
ans += c;
add(n+1+i,a,inf);
add(n+1+i,b,inf);
add(s, n+1+i, c);
}
printf("%I64d\n", ans-Dinic());
}
return 0;
}