http://acm.pku.edu.cn/JudgeOnline/problem?id=3436
题目大意:每个电脑需要P个组成部分,现有N的机器,每个机器都可以对电脑进行加工,不过加工的前提是某些部分已经存在。且每个机器的加工都有一个performance,要求能得到的最大performance.
算法分析:最大流,没用到一点优化,依然不会sap,dinic,直接bfs()搞定的,不过这次的bfs(),我没有用STL,而是手动模拟了一下,又学习到一个好的模拟队列方法,不用更新队列,直接更新长度,将值都放在同一个数组里存着,按顺序出队就行了。继续努力!
总结一点:做图论题,关键就在建图,找到建图方法,只要有模板,并且熟悉,就能很快解决了。做题时,不要过早放弃,多想想,别太早就去翻标程,这样不容易达到锻炼思维,锻炼自己分析问题,快速建图的目的。
代码
#include<stdio.h>
#include<string.h>
#define INF 0xfffffff
int perf[55], f[55][15];
int c[55][55], g[55][15], cc[55][55];
int pre[55];
int P, N;
int Min(int a, int b){return a < b ? a : b;}
/*这题关键是在建图,可以拆点,也可以不拆点,我采用的是不拆点,直接增加一个源点0和一个汇点N + 1,
所有input specification 不含1的机器都可以和源点相连,output specification全是1的都指向汇点*/
void CreatGraph()
{
int i, j, k, flag;
memset(c, 0, sizeof(c));
for (i = 1; i <= N; i++){
for (j = 1; j <= N; j++){
flag = 0;
for (k = 1; k <= P; k++){
if (i != j && g[i][k] + f[j][k] == 1){
flag = 1;
}
}
if (!flag) c[i][j] = Min(perf[i], perf[j]);
}
}
for (i = 1; i <= N; i++){
flag = 0;
for (j = 1; j <= P; j++){
if (f[i][j] == 1)
flag = 1;
}
if (!flag) c[0][i] = perf[i];
flag = 0;
for (j = 1; j <= P; j++){
if (g[i][j] == 0)
flag = 1;
}
if (!flag) c[i][N + 1] = perf[i];
}
}
int bfs()
{
int visit[55];
int num = 1;
int i, j, min, cur;
int que[55];
que[0] = 0;
memset(pre, -1, sizeof(pre));
memset(visit, 0, sizeof(visit));
visit[0] = 1;
min = INF;
/* 这种模拟队列的方法很不错,将所有节点都只放到一个数组里,
不用更新队列,只更新队列的长度,并不断将点往后加就行了*/
for (i = 0; i < num; i++){
cur = que[i];
for (j = 0; j <= N + 1; j++){
if (!visit[j] && c[cur][j] > 0){
if (c[cur][j] < min)
min = c[cur][j];
visit[j] = 1;
que[num++] = j;
pre[j] = cur;
if (j == N + 1)
break;
}
}
if (j <= N + 1)
break;
}
if (i >= num)
return -1;
else
return min;
}
void Ford_Fulkerson()
{
int f, t, tt, i, j, cnt;
int maxflow = 0;
int index = 0;
memcpy(cc, c, sizeof(c));
while ((f = bfs()) != -1){
maxflow += f;
t = N + 1;
while (t != 0){
tt = pre[t];
c[tt][t] -= f;
c[t][tt] += f;
t = tt;
}
}
cnt = 0;
for (i = 1; i <= N; i++){
for (j = 1; j <= N; j++){
if (cc[i][j] - c[i][j] > 0)
cnt++;
}
}
printf("%d %d\n", maxflow, cnt);
for (i = 1; i <= N; i++){
for (j = 1; j <= N; j++){
if (cc[i][j] - c[i][j] > 0){
printf("%d %d %d\n", i, j, cc[i][j] - c[i][j]);
}
}
}
}
int main()
{
int i, j;
while (scanf("%d%d", &P, &N) != EOF){
memset(perf, 0, sizeof(perf));
for (i = 1; i <= N; i++){
scanf("%d", &perf[i]);
for (j = 1; j <= P; j++){
scanf("%d", &f[i][j]);
}
for (j = 1; j <= P; j++){
scanf("%d", &g[i][j]);
}
}
CreatGraph();
Ford_Fulkerson();
}
return 0;
}