Educational Codeforces Round 55 (Rated for Div. 2) G Increasing Frequency(网络流 最大权闭合图)

题目链接:http://codeforces.com/contest/1082/problem/G

G. Petya and Graph

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Petya has a simple graph (that is, a graph without loops or multiple edges) consisting of nn vertices and mm edges.

The weight of the ii-th vertex is aiai.

The weight of the ii-th edge is wiwi.

A subgraph of a graph is some set of the graph vertices and some set of the graph edges. The set of edges must meet the condition: both ends of each edge from the set must belong to the chosen set of vertices.

The weight of a subgraph is the sum of the weights of its edges, minus the sum of the weights of its vertices. You need to find the maximum weight of subgraph of given graph. The given graph does not contain loops and multiple edges.

Input

The first line contains two numbers nn and mm (1≤n≤103,0≤m≤1031≤n≤103,0≤m≤103) - the number of vertices and edges in the graph, respectively.

The next line contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤1091≤ai≤109) - the weights of the vertices of the graph.

The following mm lines contain edges: the ii-e edge is defined by a triple of integers vi,ui,wivi,ui,wi (1≤vi,ui≤n,1≤wi≤109,vi≠ui1≤vi,ui≤n,1≤wi≤109,vi≠ui). This triple means that between the vertices vivi and uiui there is an edge of weight wiwi. It is guaranteed that the graph does not contain loops and multiple edges.

Output

Print one integer — the maximum weight of the subgraph of the given graph.

Examples

input

Copy

4 5
1 5 2 2
1 3 4
1 4 4
3 4 5
3 2 2
4 2 2

output

Copy

8

input

Copy

3 3
9 7 8
1 2 1
2 3 2
1 3 3

output

Copy

0

Note

In the first test example, the optimal subgraph consists of the vertices 1,3,41,3,4 and has weight 4+4+5−(1+2+2)=84+4+5−(1+2+2)=8. In the second test case, the optimal subgraph is empty.

题意:

给你n个点的权值和m带权无向条边(n,m<=1000),你要选出若干条边,获得的价值为边权总和-点权总和

读完这题感觉有点熟悉,于是...

发现我的博客里写过几乎是原题的题(只差在long long上):

HDU 3879 Base Station 最大权闭合图

博客:https://blog.csdn.net/lsd20164388/article/details/79224422

所以说 根本就是一个题了。。。只要看出来是个网络流就可以过了。。。(这道题的代码只需改改maxn就可以过HDU 3879了)

我是把hdu3879的代码改成了long long。。。就过了。。。

代码:

#include<bits/stdc++.h>
#define ll long long
#define mp make_pair
#define inf 0x3f3f3f3f3f3f3f3fLL
using namespace std;
const int maxn=60000+10;
struct edge
{
    int to,nxt;
    ll cap;
}g[maxn*10];
int head[maxn],pre[maxn],cur[maxn],gap[maxn],level[maxn];
int cnt,nv;
void add(int u,int v,ll cap)
{
    g[cnt].to=v;g[cnt].cap=cap;g[cnt].nxt=head[u];head[u]=cnt++;
    g[cnt].to=u;g[cnt].cap=0;g[cnt].nxt=head[v];head[v]=cnt++;
}
ll sap(int s,int t)
{
    memset(level,0,sizeof(level));
    memset(gap,0,sizeof(gap));
    memcpy(cur,head,sizeof(head));
    gap[0]=nv;
    int v=pre[s]=s;
    ll flow=0,aug=inf;
    while(level[s]<nv)
    {
        bool flag=false;
        for(int &i=cur[v];i!=-1;i=g[i].nxt)
        {
            int u=g[i].to;
            if(g[i].cap>0&&level[v]==level[u]+1)
            {
                flag=true;
                pre[u]=v;
                v=u;
                aug=min(aug,g[i].cap);
                if(v==t)
                {
                    flow+=aug;
                    while(v!=s)
                    {
                        v=pre[v];
                        g[cur[v]].cap-=aug;
                        g[cur[v]^1].cap+=aug;
                    }
                    aug=inf;
                }
                break;
            }
        }
        if(flag) continue;
        int minlevel=nv;
        for(int i=head[v];i!=-1;i=g[i].nxt)
        {
            int u=g[i].to;
            if(g[i].cap>0&&minlevel>level[u])
            minlevel=level[u],cur[v]=i;
        }
        if(--gap[level[v]]==0) break;
        level[v]=minlevel+1;
        gap[level[v]]++;
        v=pre[v];
    }
    return flow;
}
int n,m,a,b;
ll c;
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF){
    cnt=0;
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&c);
        add(m+i,n+m+1,c);//每个基站向汇点连边
    }
    ll sum=0;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%lld",&a,&b,&c);
        sum+=c;
        add(0,i,c);//源点和需求连边
        add(i,m+a,inf);//需求和所要求的的基站连边
        add(i,m+b,inf);
    }
    nv=n+m+2;
    printf("%lld\n",sum-sap(0,n+m+1));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/LSD20164388/article/details/84700838
今日推荐