网络流:宇宙旅行

来源:互联网 发布:云南农业大学网络考试 编辑:程序博客网 时间:2024/05/11 06:03

1. 题目要求

在走遍了地球上的所有景点以后,旅游狂人开始计划他的宇宙旅行项目。经过谨慎调查,他目前掌握了一张各卫星空间站可以临时容纳的旅客人数的列表。当旅客从一个星球飞往另一个星球时,需要在若干卫星空间站临时停靠中转,而这些空间站不能接待任何旅客驻留,旅客必须立刻转乘另一艘飞船离开,所以空间站不能接待超过自己最大容量的旅客流。为了估计预算,现在旅游狂人需要知道终点星球的接待站应该设计多大容量,才能使得每艘飞船在到达时都可以保证让全部旅客下船。

2. 输入要求

输入由若干组测试数据组成。
每组测试数据的第一行包含旅行的起点星球和终点星球的名称和一个不超过500的正整数N(N为0标志全部测试结束,不要对该数据做任何处理)。
接下来的N行里,数据格式为:(以下的i为下标)sourcei  destinationi capacityi,其中sourcei和destinationi是卫星空间站的名称或起点、终点星球的名称,正整数capacityi是飞船从sourcei到destinationi一次能运载的最大旅客流量。每个名称是由A~Z之间的3个大写字母组成的字符串,例如ZJU。
测试数据中不包含任何到达起点星球的信息以及任何从终点星球出发的信息。

3. 输出要求:

对每一组测试,在一行里输出终点星球接待站应具有的最小容量,使得每艘飞船在到达时都可以保证让全部旅客下船。

4. 输入例子

EAR MAR 8
EAR AAA 300
EAR BBB 200
AAA BBB 100
AAA CCC 300
BBB DDD 200
AAA DDD 400
CCC MAR 200
DDD MAR 300
EAR MAR  8
EAR AAA 300
AAA BBB 400
EAR DDD 200
AAA DDD 100
AAA CCC 300
DDD BBB 200
CCC MAR 200
BBB MAR 300
ABC DEF 0

5. 输出例子

500
500

6. 简要提示

该题目中给定了起点和终点(星球),其他结点(空间站)的流入量必须等于流出量,建议用网络流(Network Flow)方法解决。每次可从剩余图(Residual Graph)中找一条从起点到终点的最短路径,再按参考文献[1]中的修正算法进行。
实现时注意,程序应能在2秒内处理10组最大规模(N=500)的测试用例。为提高程序效率,需要为节点名建立散列表,避免在查找节点名上浪费时间。
所以这个题目的实现涉及3种算法:最短路径、散列映射、网络流。

测试时应注意边界测试,需要写个程序生成N为500的输入。

7.代码

#include <stdio.h>#include <string.h>#include <vector>#include<iostream>using namespace std;#define MAX_N 1001#define INF 0xffffff#define min(a, b) (a < b ? a : b)struct edge{    int to, cap;    int rev;    edge(int t, int c, int r)    {        to = t;        cap = c;        rev = r;    }};vector<edge> G[MAX_N];bool visited[MAX_N];int n, m;// 每对顶点添加正反边void addEdge(int from, int to, int cap){    G[from].push_back(edge(to, cap, G[to].size()));    G[to].push_back(edge(from, 0, G[from].size() - 1));}int dfs(int v, int t, int f){    int i;    if (v == t)    {        return f;    }    visited[v] = true;    for (i = 0; i < G[v].size(); i++)    {        edge &e = G[v][i];        if (!visited[e.to] && e.cap > 0)        {            int d = dfs(e.to, t, min(f, e.cap));            if (d > 0)            {                e.cap -= d;                G[e.to][e.rev].cap += d;                return d;            }        }    }    return 0;}int maxFlow(int s, int t){    int flow = 0;    while (true)    {        memset(visited, 0, sizeof(visited));        int f = dfs(s, t, INF);        if (f == 0)        {            return flow;        }        flow += f;    }}char points[MAX_N][4];int getIndex(char s[]){    int i;    for(i=0; i<MAX_N; i++)    {        if(strlen(points[i])==0)        {            strcpy(points[i],points[i-1]);            strcpy(points[i-1],s);            return i-1;        }        else if(strcmp(points[i],s)==0)        {            return i;        }    }    return 0;}void ini(){    int i;    for(i=0; i<MAX_N; i++)    {        G[i].clear();        points[i][0]='\0';    }}int getCount(){    int i;    for(i=0; i<MAX_N; i++)    {        if(strlen(points[i])==0)            return i;    }}int main(){    int i, j ,n;    int from, to, cap;    char src[4],des[4];    char f[4],t[4];    ini();    while(1)    {        scanf("%s%s%d",f,t,&n);        if(n==0)            break;        ini();        strcpy(points[0],f);        strcpy(points[1],t);        for(i=0; i<n; i++)        {            scanf("%s%s%d",src,des,&cap);            addEdge(getIndex(src), getIndex(des), cap);        }        printf("%d\n", maxFlow(0, getCount() - 1));    }    return 0;}


java

import java.util.*;public class Test1 {final static int max = 1001;final static int inf = 0xffffff;private static String points[] = new String[max];private static Vector<Edge> g[] = new Vector[max];private static boolean visited[] = new boolean[max];static class Edge {int to, cap, rev;Edge(int to, int cap, int rev) {this.to = to;this.cap = cap;this.rev = rev;}}public static void main(String[] args) {for (int i = 0; i < max; i++)g[i] = new Vector<Edge>();int n;int cap;String f, t;String src, des;ini();Scanner cin = new Scanner(System.in);while (true) {f = cin.next();t = cin.next();n = cin.nextInt();if (n == 0)break;ini();points[0] = f;points[1] = t;for (int i = 0; i < n; i++) {src = cin.next();des = cin.next();cap = cin.nextInt();addEdge(getIndex(src), getIndex(des), cap);}/*for (int i = 0; i < max; i++) {if (points[i] != null)System.out.println(points[i]);}*/System.out.println(maxFlow(0, getCount() - 1));}}private static void addEdge(int from, int to, int cap) {g[from].add(new Edge(to, cap, g[to].size())); //System.out.println(to+" "+cap+" "+g[to].size());g[to].add(new Edge(from, 0, g[from].size() - 1));}private static int getIndex(String s) {for (int i = 0; i < max; i++) {// if (points[i] != null)// System.out.println(points[i] + s);if (points[i] == null) {points[i] = points[i - 1];points[i - 1] = s;return i - 1;} else if (points[i].equals(s))return i;}return 0;}private static void ini() {for (int i = 0; i < max; i++) {g[i].clear();points[i] = null;}}private static int getCount() {for (int i = 0; i < max; i++) {if (points[i] == null)return i;}return 0;}private static int maxFlow(int s, int t) {int flow = 0; //System.out.println(s+" "+t+" ");while (true) {for (int i = 0; i < max; i++) {visited[i] = false;}int f = dfs(s, t, inf);if (f == 0)return flow;// System.out.println(flow);flow += f;}}private static int dfs(int v, int t, int f) {if (v == t) {return f;}visited[v] = true;for (int i = 0; i < g[v].size(); i++) {Edge e = g[v].get(i);if (!visited[e.to] && e.cap > 0) {int d = dfs(e.to, t, min(f, e.cap));// System.out.println(d);if (d > 0) {e.cap -= d;g[e.to].get(e.rev).cap += d;return d;}}}return 0;}private static int min(int a, int b) {return a > b ? b : a;}}


 

1 0
原创粉丝点击