【BNUOJ】Another Server

第十五届北京师范大学程序设计竞赛决赛

A. Another Server

何老师某天在机房里搞事情的时候,发现机房里有 n 台服务器,从1 n 标号,同时有2n2条网线,从 1 2n2标号,其中第 i 条网线双向连接着i+12号服务器和 i+12+1 号服务器,在一个单位时间内最多能够承受 xi 个单位流量。

显然这些服务器之间要进行信息交换,为了测试服务器的抗压能力,你需要帮何老师计算出 1 号服务器在一个单位时间内最多能向n号服务器发送多少个单位流量的数据,这里认为数据的传输是瞬间完成的。
这里写图片描述
(该图引用自百度百科)

Input

第一行是一个正整数 T(1000) ,表示测试数据的组数,对于每组测试数据,第一行是一个整数 n(2n100) ,表示服务器的数量,

第二行包含 2n2 个以空格分隔的正整数 x1,x2,...,x2n2 ,表示网线单位时间内能承受的流量,保证不超过 100

Output

对于每组测试数据,输出一个整数,表示 1 号服务器在一个单位时间内最多能向n号服务器发送的数据量。

Sample Input

2
2
1 1
3
1 3 2 4

Sample Output

2
4

Hint

x 表示不大于 x 的最大整数,例如1.5=1,2=2

题解

1 为源点n为汇点,按照题目中的要求建边,跑最大流即可。

代码

#include <bits/stdc++.h>

using namespace std;
const int maxn = 510;
const int inf = 1e9+1;
int T, n, m;
int head[maxn], nxt[maxn], to[maxn], flow[maxn], mxflow[maxn], cnt;
int dep[maxn], q[maxn], cur[maxn];
bool vis[maxn];
void add(int a, int b, int c){
    nxt[++ cnt] = head[a], to[head[a] = cnt] = b, mxflow[cnt] = c, flow[cnt] = 0;
    nxt[++ cnt] = head[b], to[head[b] = cnt] = a, mxflow[cnt] = 0, flow[cnt] = 0;
}

bool bfs(){
    for(int i = 1; i <= n; i ++){
        vis[i] = 0, dep[i] = 0;
    }
    int l = 1, r = 0; q[++ r] = 1, vis[1] = 1, dep[1] = 1;
    while(l <= r){
        int x = q[l ++];
        for(int i = head[x]; i; i = nxt[i]){
            int u = to[i];
            if(!vis[u] && flow[i] < mxflow[i]){
                q[++ r] = u, dep[u] = dep[x] + 1, vis[u] = 1; 
            }
        }
    }
    return vis[n];
}

int dfs(int x, int mr){
    if(x == n || mr == 0) return mr;
    int &i = cur[x];
    int f = 0, res = 0, u;
    for( ; i; i = nxt[i]){
        u = to[i];
        if(dep[x]+1 == dep[u] && (f = dfs(u, min(mr, mxflow[i] - flow[i])))){
            flow[i] += f, flow[i^1] -= f;
            mr -= f, res += f;
        }
        if(mr == 0) break;
    } 
    return res;
}

int dinic(){
    int res = 0;
    while(bfs()){
        for(int i = 1; i <= n; i ++) cur[i] = head[i];
        res += dfs(1, inf);
    }
    return res;
}

int main(){
    scanf("%d", &T);
    while(T --){
        scanf("%d", &n);
        m = 2*n-2, cnt = 1;
        for(int i = 1; i <= n; i ++) head[i] = 0;
        for(int i = 1; i <= m; i ++){
            int v; scanf("%d", &v);
            add((i+1)/2, (i+1)/2+1, v);
        } 
        printf("%d\n", dinic());
    } 

    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值