/*题意中给出多个节点和多个发电站与消费站。可以建一个虚拟的源点和虚拟的汇点,将所有的发电站和源点连一条边,将所有的消费占和汇点连一条边。
然后利用网络流建图即可。下面是SAP算法。*/
#include <cstring>
#include <iostream>
#include <cstdio>
#define SETZR(a) memset(a,0,sizeof(a))
using namespace std;
const int MAXM = 100001;
const int MAXN = 301;
const int INF = 1000000000;
struct record
{
int v, f, next;
} edge[MAXM];
int n, m, s, t, cas, cl;
int pointer[MAXN], dis[MAXN], vh[MAXN];
int his[MAXN], di[MAXN], pre[MAXN];
void add(int a, int b, int f)
{
cl++;
edge[cl].next = pointer[a];
edge[cl].v = b;
edge[cl].f = f;
pointer[a] = cl;
cl++;
edge[cl].next = pointer[b];
edge[cl].v = a;
edge[cl].f = 0;
pointer[b] = cl;
}
void maxflow()
{
vh[0] = n;
for (int i = 0; i < n; i++) di[i] = pointer[i];
int i = s, aug = INF, flow = 0;
bool flag = 0;
while (dis[s] < n)
{
his[i] = aug;
flag = 0;
int p = di[i];
while (p != 0)
{
if ((edge[p].f > 0) && (dis[edge[p].v] + 1 == dis[i]))
{
flag = 1;
di[i] = p;
aug = min(aug, edge[p].f);
pre[edge[p].v] = p;
i = edge[p].v;
if (i == t)
{
flow += aug;
while (i != s)
{
edge[pre[i]].f -= aug;
edge[pre[i]^1].f += aug;
i = edge[pre[i]^1].v;
}
aug = INF;
}
break;
}
p = edge[p].next;
}
if (flag) continue;
int min = n - 1;
p = pointer[i];
while (p != 0)
{
if ((edge[p].f > 0) && (dis[edge[p].v] < min))
{
di[i] = p;
min = dis[edge[p].v];
}
p = edge[p].next;
}
--vh[dis[i]];
if (vh[dis[i]] == 0) break;
dis[i] = min + 1;
++vh[dis[i]];
if (i != s)
{
i = edge[pre[i]^1].v;
aug = his[i];
}
}
printf("%d\n", flow);
}
int main()
{
int np,nc;
while(scanf("%d%d%d%d",&n,&np,&nc,&m)==4)
{
cl = 1;
SETZR(dis);
SETZR(vh);
SETZR(pointer);
int a,b,c;
while(m--)
{
scanf(" (%d,%d)%d",&a,&b,&c);
add(a+1,b+1,c);
}
while(np--)
{
scanf(" (%d)%d",&a,&b);
add(0,a+1,b);
}
while(nc--)
{
scanf(" (%d)%d",&a,&b);
add(a+1,n+1,b);
}
s=0;
t=n+1;
n+=2;
maxflow();
}
return 0;
}
Power Network 最大流基础 hoj
最新推荐文章于 2017-09-04 19:40:20 发布