URAL 1664
这个题目中间有一大段是用来迷惑的,其实源点就是1,汇点就是N。
最后输出的时候注意流量要从A流到B即可,并且每条边要顺序输出。
#include<stdio.h>
#include<string.h>
#define INF 0x7FFFFFFF
#define MAXD 10010
#define MAXM 10000010
int first[MAXD], next[MAXM], u[MAXM], v[MAXM], N, M, e;
long long int cap[MAXM], flow[MAXM];
int S, T, work[MAXD], d[MAXD], q[MAXD], s[MAXD];
void add(int a, int b, int w)
{
u[e] = a;
v[e] = b;
cap[e] = flow[e] = w;
next[e] = first[a];
first[a] = e;
e ++;
}
int init()
{
int i, minx, maxx, x, y, a, b, w;
if(scanf("%d", &N) != 1)
return 0;
minx = INF;
maxx = 0;
for(i = 1; i <= N; i ++)
scanf("%d%d", &x, &y);
S = 1;
T = N;
scanf("%d", &M);
memset(first, -1, sizeof(first));
e = 0;
for(i = 0; i < M; i ++)
{
scanf("%d%d%d", &a, &b, &w);
add(a, b, w);
add(b, a, w);
}
return 1;
}
int bfs()
{
int i, j, rear;
memset(d, -1, sizeof(d));
rear = 0;
d[S] = 0;
q[rear ++] = S;
for(i = 0; i < rear; i ++)
for(j = first[q[i]]; j != -1; j = next[j])
if(flow[j] && d[v[j]] == -1)
{
d[v[j]] = d[q[i]] + 1;
if(v[j] == T)
return 1;
q[rear ++] = v[j];
}
return 0;
}
int dinic()
{
int cur, res = 0, r;
while(bfs())
{
memcpy(work, first, sizeof(first));
r = 0;
cur = S;
for(;;)
{
if(cur == T)
{
int minr = 0, a = INF;
for(int i = 0; i < r; i ++)
if(flow[s[i]] < a)
{
a = flow[s[i]];
minr = i;
}
for(int i = 0; i < r; i ++)
{
flow[s[i]] -= a;
flow[s[i] ^ 1] += a;
}
r = minr;
cur = u[s[r]];
res += a;
}
int i;
for(i = work[cur]; i != -1; i = next[i])
{
if(flow[i] == 0)
continue;
if(d[cur] + 1 == d[v[i]])
break;
}
work[cur] = i;
if(i != -1)
{
s[r ++] = i;
cur = v[i];
}
else
{
d[cur] = -1;
if(r == 0)
break;
r --;
cur = u[s[r]];
}
}
}
return res;
}
void printresult()
{
int i;
for(i = 0; i < 2 * M; i += 2)
{
if(flow[i] > cap[i])
printf("%d %d %I64d\n", u[i ^ 1], v[i ^ 1], cap[i ^ 1] - flow[i ^ 1]);
else
printf("%d %d %I64d\n", u[i], v[i], cap[i] - flow[i]);
}
}
int main()
{
while(init())
{
long long int res = dinic();
printf("%I64d\n", res);
printresult();
}
return 0;
}