2011-12-18 15:04:21 +01:00

191 lines
4.4 KiB
Plaintext

Christian Sinschek
fordfulk.tri berechnet den maximalen Fluss in einem gerichteten Flussgraphen
Eingabeformat:
Input -> Knotenzahl Kantenzahl Kanten
Kanten-> Startpunkt Flussmenge Endpunkt
{alle nicht-Terminale nur auf rechten Seiten} -> int
z.B. gut lesbar so zu schreiben, da Triangle auf Zeilenumbrüche "wartet"
4 3
0 3 1
1 2 2
1 2 3
Arrays in Triangle- auch der neuen Version- können leider mit allen Verschachtelungen nur eine Größe von 225 Feldern haben, daher sind die Netzwerke auf 15 Knoten, also eine 15x15- Flussmatrix beschränkt.
Ausgabe ist einfach der Maxflow.
Hier der C-Quellcode von
http://www.aduni.org/courses/algorithms/courseware/handouts/Reciation_09.html
(unten weiter)
// The Ford-Fulkerson Algorithm in C
#include <stdio.h>
Basic Definitions
#define WHITE 0
#define GRAY 1
#define BLACK 2
#define MAX_NODES 1000
#define oo 1000000000
// Declarations
int n; // number of nodes
int e; // number of edges
int capacity[MAX_NODES][MAX_NODES]; // capacity matrix
int flow[MAX_NODES][MAX_NODES]; // flow matrix
int color[MAX_NODES]; // needed for breadth-first search
int pred[MAX_NODES]; // array to store augmenting path
int min (int x, int y) {
return x<y ? x : y; // returns minimum of x and y
}
// A Queue for Breadth-First Search
int head,tail;
int q[MAX_NODES+2];
void enqueue (int x) {
q[tail] = x;
tail++;
color[x] = GRAY;
}
int dequeue () {
int x = q[head];
head++;
color[x] = BLACK;
return x;
}
// Breadth-First Search for an augmenting path
int bfs (int start, int target) {
int u,v;
for (u=0; u<n; u++) {
color[u] = WHITE;
}
head = tail = 0;
enqueue(start);
pred[start] = -1;
while (head!=tail) {
u = dequeue();
// Search all adjacent white nodes v. If the capacity
// from u to v in the residual network is positive,
// enqueue v.
for (v=0; v<n; v++) {
if (color[v]==WHITE && capacity[u][v]-flow[u][v]>0) {
enqueue(v);
pred[v] = u;
}
}
}
// If the color of the target node is black now,
// it means that we reached it.
return color[target]==BLACK;
}
// Ford-Fulkerson Algorithm
int max_flow (int source, int sink) {
int i,j,u;
// Initialize empty flow.
int max_flow = 0;
for (i=0; i<n; i++) {
for (j=0; j<n; j++) {
flow[i][j] = 0;
}
}
// While there exists an augmenting path,
// increment the flow along this path.
while (bfs(source,sink)) {
// Determine the amount by which we can increment the flow.
int increment = oo;
for (u=n-1; pred[u]>=0; u=pred[u]) {
increment = min(increment,capacity[pred[u]][u]-flow[pred[u]][u]);
}
// Now increment the flow.
for (u=n-1; pred[u]>=0; u=pred[u]) {
flow[pred[u]][u] += increment;
flow[u][pred[u]] -= increment;
}
max_flow += increment;
}
// No augmenting path anymore. We are done.
return max_flow;
}
// Reading the input file and the main program
void read_input_file() {
int a,b,c,i,j;
FILE* input = fopen("mf.in","r");
// read number of nodes and edges
fscanf(input,"%d %d",&n,&e);
// initialize empty capacity matrix
for (i=0; i<n; i++) {
for (j=0; j<n; j++) {
capacity[i][j] = 0;
}
}
// read edge capacities
for (i=0; i<e; i++) {
fscanf(input,"%d %d %d",&a,&b,&c);
capacity[a][b] = c;
}
fclose(input);
}
int main () {
read_input_file();
printf("%d\n",max_flow(0,n-1));
return 0;
}
Beim Programmieren war mir nicht bewusst, dass Triangle ein Konzept lokaler Sichbarkeit globaler Variablen haben könnte, deshalb werden alle Variablen z. T. redundant übergeben. Ob Compiler-Optimierungen da sinnvoll eingreifen weis ich erstn, wenn ich weiss wie wir den Compiler optimieren (der Fall ist doch recht dämlich), aber ich habe es dennoch mal so gelassen.
Größtes "Problem" des Algorithmus ist seine geringe Laufzeit, zumindest funktionale Äquivalenz der Compiler sollte sollte ich zeigen lassen.
Beispieleingaben, zu machen auch durch einfaches c+p
6 9
0 5 1
0 7 2
1 7 2
1 4 3
2 3 4
2 3 3
3 4 4
3 5 5
4 6 5
9 15
0 8 1
1 3 3
2 3 4
4 2 6
5 2 7
7 5 8
3 2 6
6 4 8
1 4 4
4 4 7
0 7 2
2 2 5
2 2 7
4 8 8
1 5 6
Die Beispiele entsprechen der GDI3 vom WS 04/05, Skript 3, Folie 29/30 links oben und Übung/Musterlösung 5