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;
}