【最大流】LightOJ-1153 Internet Bandwidth

本文介绍了一种计算网络中两节点间最大带宽的方法,并通过一个具体的编程实现展示了如何求解这一问题。针对给定的网络连接及其带宽,利用改进的Dinic算法找到了所有可能路径上的总带宽。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1153 - Internet Bandwidth
Time Limit: 2 second(s)Memory Limit: 32 MB

On the Internet, machines (nodes) are richly interconnected, and many paths may exist between a given pair of nodes. The total message-carrying capacity (bandwidth) between two given nodes is the maximal amount of data per unit time that can be transmitted from one node to the other. Using a technique called packet switching; this data can be transmitted along several paths at the same time.

For example, the following figure shows a network with four nodes (shown as circles), with a total of five connections among them. Every connection is labeled with a bandwidth that represents its data-carrying capacity per unit time.

In our example, the bandwidth between node 1 and node 4 is 25, which might be thought of as the sum of the bandwidths 10 along the path 1-2-4, 10 along the path 1-3-4, and 5 along the path 1-2-3-4. No other combination of paths between nodes 1 and 4 provides a larger bandwidth.

You must write a program that computes the bandwidth between two given nodes in a network, given the individual bandwidths of all the connections in the network. In this problem, assume that the bandwidth of a connection is always the same in both directions (which is not necessarily true in the real world).

Input

Input starts with an integer T (≤ 30), denoting the number of test cases.

Every description starts with a line containing an integer n (2 ≤ n ≤ 100), which is the number of nodes in the network. The nodes are numbered from 1 to n. The next line contains three numbers st, and c. The numbers s and t are the source and destination nodes, and the number c (c ≤ 5000, s ≠ t) is the total number of connections in the network. Following this are c lines describing the connections. Each of these lines contains three integers: the first two are the numbers of the connected nodes, and the third number is the bandwidth of the connection. The bandwidth is a non-negative number not greater than 1000.

There might be more than one connection between a pair of nodes, but a node cannot be connected to itself. All connections are bi-directional, i.e. data can be transmitted in both directions along a connection, but the sum of the amount of data transmitted in both directions must be less than the bandwidth.

Output

For each case of input, print the case number and the total bandwidth between the source node s and the destination node t.

Sample Input

Output for Sample Input

2

4

1 4 5

1 2 20

1 3 10

2 3 5

2 4 10

3 4 20

4

1 4 2

1 4 20

1 4 20

Case 1: 25

Case 2: 40

 


前言:一个泰国人做的OJ?……既然听说有分类,那就混个脸熟先。

思路:之前以为就是模板题,结果死活过不了,后来才发现,题意真的没看懂。。。是因为英语的原因么……建图的方式很奇怪,不过这让我知道了不添加超级源点、超级汇点也是可以的。

每条边正向反向的权值一样就好了。。。

因为根据题意,正向反向都一样……(a connection is always the same in both directions)所以反向流量到时候会自动增广,流入正向弧中。

代码如下:

/*
ID: j.sure.1
PROG:
LANG: C++
*/
/****************************************/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <climits>
#include <iostream>
#define INF 0x3f3f3f3f
using namespace std;
/****************************************/
const int N = 1000, M = 1e5;
struct Node {
    int u, v, cap;
	int next;
} edge[M];
int tot, lev[N], head[N], q[N], cur[N], s[N], S, T;
int n, m;

void init()
{
    tot = 0;
    memset(head, -1, sizeof(head));
}

void add(int u,int v,int c)
{
    edge[tot].u = u; edge[tot].v = v; edge[tot].cap = c;
    edge[tot].next = head[u]; head[u] = tot++;
}

bool bfs()
{
    memset(lev, -1, sizeof(lev));
    int fron = 0, rear = 0;
    q[rear++] = S;
    lev[S] = 0;
    while(fron < rear) {
        int u = q[fron%N]; fron++;
        for(int i = head[u]; i != -1; i = edge[i].next) {
            int v = edge[i].v;
            if(edge[i].cap && lev[v] == -1) {
                lev[v] = lev[u] + 1;
                q[rear%N] = v; rear++;
                if(v == T) return true;
            }
        }
    }
    return false;
}

int Dinic()
{
    int ret = 0;
    while(bfs()) {
        memcpy(cur, head, sizeof(head));
        int u = S, top = 0;
        while(1) {
            if(u == T) {
                int mini = INF, loc;
                for(int i = 0; i < top; i++) {
                    if(mini > edge[s[i]].cap) {
                        mini = edge[s[i]].cap;
                        loc = i;
                    }
				}
                for(int i = 0; i < top; i++) {
                    edge[s[i]].cap -= mini;
                    edge[s[i]^1].cap += mini;
                }
                ret += mini;
                top = loc;
                u = edge[s[top]].u;
            }
			int &i = cur[u];
            for(; i != -1; i = edge[i].next) {
				int v = edge[i].v;
                if(edge[i].cap && lev[v] == lev[u] + 1) break;
			}
            if(i != -1) {
                s[top++] = i;
                u = edge[i].v;
            }
            else {
                if(!top) break;
                lev[u] = -1;
                u = edge[s[--top]].u;
            }
        }
    }
    return ret;
}

int main()
{
	int TT, cas = 1;
	scanf("%d", &TT);
	while(TT--) {
		init();
		scanf("%d", &n);
		int x, y, c;
		scanf("%d%d%d", &x, &y, &m);
		S = x; T = y;
		for(int i = 1; i <= m; i++) {
			scanf("%d%d%d", &x, &y, &c);
			add(x, y, c); add(y, x, c);
		}
		printf("Case %d: %d\n", cas++, Dinic());
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值