这个题出的很不错……伪装的很好!想,如果当年做过employee该多好~一个极度无语的网络流,伪装成高斯消元……这个思想值得借鉴。。
如果要做这个题,建议先做employee,体会连边方式,可以参考napkin。这几个题都有共同点,值得一做。
核心:把未知量看成边,把方程看成点,最大流的用处只是为了分配流量。。
照例code,99行的sap:
#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <math.h>
#define maxn 40050
#define maxm 40050
#define maxk 500500
#define maxv (maxn + maxm + 1)
#define maxe (maxv + maxk * 2)
#define oo 0x3F3F3F3F
typedef struct {int t, c, n;} etype;
int A[maxk];
int adm[maxv];
etype g[maxe << 1];
int vexsize, etop = 1, src, sink;
int dist[maxv];
int edge[maxv];
int gap[maxv], *queue = adm;
int pred[maxv];
void augment ()
{
int i, e, width = oo;
for (i = src, e = adm[i]; i != sink; i = g[e].t, e = adm[i])
if (g[e].c < width)
width = g[e].c;
for (i = src, e = adm[i]; i != sink; i = g[e].t, e = adm[i])
g[e].c -= width, g[e ^ 1].c += width;
}
void rev_bfs ()
{
memset (dist, 0x3F, sizeof (dist)), dist[sink] = 0;
int head = 0, tail = 0, i, e, dtmp, p;
queue[++tail] = sink;
for (; head != tail; )
for (e = edge[i = queue[++head]], dtmp = dist[i] + 1; e; e = g[e].n)
if (dist[p = g[e].t] > dtmp)
gap[dist[queue[++tail] = p] = dtmp]++;
vexsize = tail;
}
void isap ()
{
rev_bfs ();
memcpy (adm, edge, sizeof (adm));
int i = src, e, dtmp, mindist;
for (; dist[src] != vexsize; )
{
for (e = adm[i], dtmp = dist[i] - 1; e; e = g[e].n)
if (g[e].c && dist[g[e].t] == dtmp)
break;
if (e)
{
adm[i] = e;
pred[g[e].t] = i;
i = g[e].t;
if (i == sink)
augment (), i = src;
}
else
{
if ((--gap[dist[i]]) == 0) return;
e = adm[i] = edge[i];
for (mindist = vexsize - 1; e; e = g[e].n)
if (g[e].c && mindist > dist[g[e].t])
mindist = dist[g[e].t];
gap[dist[i] = mindist + 1]++;
if (i != src) i = pred[i];
}
}
}
void adde (int s, int t, int c)
{
g[++etop] = (etype){t, c, edge[s]}, edge[s] = etop;
g[++etop] = (etype){s, 0, edge[t]}, edge[t] = etop;
}
int main ()
{
freopen ("matrix.in" , "r", stdin);
freopen ("matrix.out", "w", stdout);
int n, m, k, i, x, y, u, v;
scanf ("%d%d%d", &n, &m, &k), src = n + m + 1, sink = src + 1;
for (i = 1; i <= k; ++i)
scanf ("%d%d%d", &x, &y, &A[i]), adde (x, y + n, oo), adde (y + n, x, oo);
for (i = 1; i <= n; ++i)
scanf ("%d", &u), u ? adde (src, i, u) : 0;
for (i = 1; i <= m; ++i)
scanf ("%d", &v), v ? adde (i + n, sink, v) : 0;
isap ();
for (i = 1; i <= k; ++i)
printf ("%0.8lf\n", 1.0 * (g[(i << 2) - 1].c - g[(i << 2) + 1].c) / A[i]);
return 0;
}