1 /*
2 hdu 3917 Road constructions 最大权闭合图
3 题意:n个城市 m个工程公司修路 每个公司要交税收 有k个路段 分别花销cost
4 当如果选择了某个公司,该公司负责的所有的路都要选,还有如果1->2的路由公司A负责,
5 2->3的路由公司B负责,那么如果选了公司A就必须选公司B, 求最大的收益
6 建图:税收为正权值、cost为负权值 start连所有公司m end连所有公司m
7 规则要求联系的公司之间为INF eg addedge(a,b,INF);该处解决方法建结构体详见具体代码
8 start=0;end=1+m;totals=end+1;
9 建图完成
10 答案:最大权闭合图。一模一样的。答案为税收总和-最大流
11 */
12 #include <iostream>
13 #include<cstdio>
14 #include<cstring>
15 #include<vector>
16 #include<queue>
17 #include<algorithm>
18 using namespace std;
19 #define min(a,b) ((a)<(b))?(a):(b)
20 #define max(a,b) ((a)>(b))?(a):(b)
21 #define MAXN 6005//尽量开大点
22 #define MAXM 100002 //M取N的平方倍或者N*9
23 #define INF 0x3f3f3f3f
24 int m,n;
25 struct node
26 {
27 int n;//点编号
28 int w;//点权
29 }Node[MAXM];//n变m
30 //链式前向星
31 struct s//存工程每个工程公司修路的起点终点
32 {
33 int s;//起点
34 int t;//终点
35 int c;//该公司名称
36 }ss[MAXN];
37 struct enode
38 {
39 int t;
40 int w; //权值
41 int c; //流量
42 // int cost;
43 // int pre; //前向指针
44 int next;
45 };
46
47 struct enode e[MAXM];
48 int box[MAXN],ecnt;
49 //int etail[MAXN]; //尾部
50 void init()
51 {
52 ecnt=0;
53 memset(box,-1,sizeof(box));
54 // memset(etail,-1,sizeof(etail)); //初始化尾部
55 }
56 void addedge(int f,int t,int c) //流量重载
57 {
58 e[ecnt].next=box[f];
59 e[ecnt].t=t;
60 e[ecnt].c=c;
61 box[f]=ecnt++;
62 e[ecnt].next=box[t];
63 e[ecnt].t=f;
64 e[ecnt].c=0;
65 box[t]=ecnt++;
66 }
67 int sap(int s,int t,int N)//最大流问题
68 {
69 int gap[MAXN],lvl[MAXN],cur[MAXN],pre[MAXN];
70 int curflow,ans=0,u,tmp,neck,i;
71 memset(lvl,0,sizeof(lvl));
72 memset(gap,0,sizeof(gap));
73 memset(pre,-1,sizeof(pre));
74 for(i=0;i<N;i++)
75 cur[i]=box[i];
76 gap[0]=N;
77 u=s;
78 while(lvl[s]<N)
79 {
80 if(u==t)
81 {
82 curflow=INF;
83 for(i=s;i!=t;i=e[cur[i]].t)
84 {
85 if(curflow>e[cur[i]].c)
86 {
87 neck=i;
88 curflow=e[cur[i]].c;
89 }
90 }
91 for(i=s;i!=t;i=e[cur[i]].t)
92 {
93 tmp=cur[i];
94 e[tmp].c-=curflow;
95 e[tmp^1].c+=curflow;
96 }
97 ans+=curflow;
98 u=neck;
99 }
100 for(i=cur[u];i!=-1;i=e[i].next)
101 if(e[i].c && lvl[u]==lvl[e[i].t]+1)
102 break;
103 if(i!=-1)
104 {
105 cur[u]=i;
106 pre[e[i].t]=u;
107 u=e[i].t;
108 }
109 else
110 {
111 if(--gap[lvl[u]]==0)
112 break;
113 cur[u]=box[u];
114 for(tmp=N,i=box[u];i!=-1;i=e[i].next)
115 if(e[i].c)
116 tmp=min(tmp,lvl[e[i].t]);
117 lvl[u]=tmp+1;
118 gap[lvl[u]]++;
119 if(u!=s)
120 u=pre[u];
121 }
122 }
123 return ans;
124 }
125 int index[5010];
126 int main()
127 {
128 int a,b,c,d,t,k,w,ct;
129 int i,j;
130 int start,end,ans;
131 while(scanf("%d%d",&n,&m)&&n&&m) //;
132 {
133 // if(m==0&&n==0)break;
134 start=ans=ct=0;
135 end=1+m;//终点编号
136 init();
137 memset(index,0,sizeof(index));
138 for(i=1;i<=m;i++)
139 {
140 scanf("%d",&w);
141 addedge(start,i,w);//起点连公司 税收为正值
142 ans+=w;//正权值累加
143 }
144 scanf("%d",&k);
145 for(i=1;i<=k;i++)
146 {
147 scanf("%d%d%d%d",&a,&b,&c,&d);
148 ss[i].s=a; ss[i].t=b;
149 ss[i].c=c;
150 index[c]+=d;//对应工程公司付费求和 减小建边次数
151 //addedge(c,end,d);
152 }
153 for(i=1;i<=m;i++)
154 {
155 addedge(i,end,index[i]);//公司连终点
156 }
157 for(i=1;i<=k;i++)//k个公路条件
158 {
159 for(j=1;j<=k;j++)
160 {
161 if(ss[i].t==ss[j].s&&(i!=j)&&ss[i].c!=ss[j].c)
162 {
163 addedge(ss[i].c,ss[j].c,INF);
164 }
165 }
166 }
167
168 t=sap( start,end,end+1);
169 printf("%d\n",ans-t);
170 }
171 return 0;
172 }
173 /*
174 4 2
175 500 10
176 4
177 1 2 1 10
178 2 3 1 20
179 4 3 1 30
180 1 4 2 60
181 4 2
182 500 100
183 5
184 1 2 1 10
185 2 3 1 20
186 4 3 1 30
187 4 3 2 10
188 1 4 2 60
189 3 1
190 10
191 3
192 1 2 1 100
193 2 3 1 100
194 3 1 1 100
195 0 0
196
197
198
199 Sample Output
200
201 440
202 470
203 0
204 */
//http://acm.hdu.edu.cn/webcontest/contest_showproblem.php?cid=4456&pid=1010&ojid=0