昨天TMD又没做出网络流。。就因为一句话看不懂。。悲剧。。题目应该是很好理解。。就是其中的一个括号要少为理解一下。。就是说工程队A要造1到2的路,工程队B要造2到3的路,就说工程队A和工程队B是有关系的。。这个要是理解了,最小割模型就可以构造了。。把每个工程队的税收为正权,连源点 。每个工程队的施工总和为 C[i],连汇点,值为C[i];
有联系的工程队之间连有向边,边权为inf。。最大权闭包的题目,关键在怎么建图用最大流来求 。。
答案为所以税收总和-最大流
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 5005
#define M 40005 //这个要够大。。
#define inf 999999999
using namespace std;
int n,m,s,t,num,adj[N],dis[N],q[N],tmp;
struct edge
{
int v,w,pre;
}e[M];
int min(int x,int y)
{
if(x>y)
return y;
else
return x;
}
void insert(int u,int v,int w)
{
e[num].v=v;
e[num].w=w;
e[num].pre=adj[u];
adj[u]=num++;
e[num].v=u;
e[num].w=0;
e[num].pre=adj[v];
adj[v]=num++;
}
int bfs()
{
int i,x,v,tail=0,head=0;
memset(dis,0,sizeof(dis));
dis[s]=1;
q[tail++]=s;
while(head<tail)
{
x=q[head++];
for(i=adj[x];i!=-1;i=e[i].pre)
if(e[i].w&&dis[v=e[i].v]==0)
{
dis[v]=dis[x]+1;
if(v==t)
return 1;
q[tail++]=v;
}
}
return 0;
}
int dfs(int s,int limit)
{
if(s==t)
return limit;
int i,v,tmp,cost=0;
for(i=adj[s];i!=-1;i=e[i].pre)
if(e[i].w&&dis[s]==dis[v=e[i].v]-1)
{
tmp=dfs(v,min(limit-cost,e[i].w));
if(tmp>0)
{
e[i].w-=tmp;
e[i^1].w+=tmp;
cost+=tmp;
if(limit==cost)
break;
}
else dis[v]=-1;
}
return cost;
}
int Dinic()
{
int ans=0;
while(bfs())
ans+=dfs(s,inf);
return ans;
}
int C[5001];
struct E
{
int a,b,c;
}Team[3003];
int main()
{
int i,j,Q;
while(scanf("%d%d",&n,&m),n+m)
{
memset(adj,-1,sizeof(adj));
num=0;
int sum=0,sum1=0;
for(i=1;i<=m;i++)
{
scanf("%d",&tmp);
insert(0,i,tmp);//0为汇点
sum1+=tmp;
C[i]=0;
}
scanf("%d",&Q);
for(i=1;i<=Q;i++)
{
scanf("%d%d%d%d",&Team[i].a,&Team[i].b,&Team[i].c,&tmp);
C[Team[i].c]+=tmp;//记住每个工程队的税收。。
}
for(i=1;i<=Q;i++)
{
for(j=1;j<=Q;j++)if(i!=j)
{
if(Team[i].c!=Team[j].c&&Team[i].b==Team[j].a) //这里不懂得话在纸上画一画就懂了。。判断两个工程队是不是有关系。。
insert(Team[i].c,Team[j].c,inf);
}
}
for(i=1;i<=m;i++)
{
insert(i,m+1,C[i]);
}
s=0;
t=m+1;
int ans=sum1-Dinic();
if(ans<0)
ans=0;
printf("%d\n",ans);
}
return 0;
}