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.
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,
Ai,Bi
and
Ci
, 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
题目大意:修建一些通讯站,每个通讯站的修建需要一些花费, 但是某些两个通讯站修建了以后会有利润,求最大利润,这题需要把利润抽象出来成一个点,然后和相应的两个通讯站连有向便,最高就是最大全闭合字图的模型了,利润点都和原点相连,站点都和汇点响亮,利润点和站点的边权为无穷大。难度中等
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=55005;
const int maxx=610005;
int edge;
int to[maxx],flow[maxx],nex[maxx];
int head[maxn];
void addEdge(int v,int u,int cap)
{
to[edge]=u,flow[edge]=cap,nex[edge]=head[v],head[v]=edge++;
to[edge]=v,flow[edge]=0,nex[edge]=head[u],head[u]=edge++;
}
int vis[maxn];
int pre[maxn];
bool bfs(int s,int e)
{
queue<int> que;
pre[s]=-1;
memset(vis,-1,sizeof(vis));
que.push(s);
vis[s]=0;
while(!que.empty())
{
int u=que.front();
que.pop();
for(int i=head[u];~i;i=nex[i])
{
int v=to[i];
if(vis[v]==-1&&flow[i])
{
vis[v]=vis[u]+1;
if(v==e)
return true;
que.push(v);
}
}
}
return false;
}
int dfs(int s,int t,int f)
{
if(s==t||!f)
return f;
int r=0;
for(int i=head[s];~i;i=nex[i])
{
int v=to[i];
if(vis[v]==vis[s]+1&&flow[i])
{
int d=dfs(v,t,min(f,flow[i]));
if(d>0)
{
flow[i]-=d;
flow[i^1]+=d;
r+=d;
f-=d;
if(!f)
break;
}
}
}
if(!r)
vis[s]=INF;
return r;
}
int maxFlow(int s ,int e)//然后直接调用这个即可
{
int ans=0;
while(bfs(s,e))
ans+=dfs(s,e,INF);
return ans;
}
void init()//记得每次使用前初始化
{
memset(head,-1,sizeof(head));
edge=0;
}
int main()
{
int n,m;
int x,y,w;
while(scanf("%d%d",&n,&m)==2)
{
int total=0;
int s=n+m+1;
init();
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
addEdge(i,s,x);
}
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&w);
total+=w;
addEdge(0,n+i,w);
addEdge(n+i,x,INF);
addEdge(n+i,y,INF);
}
printf("%d\n",total-maxFlow(0,s));
}
return 0;
}