zoukankan      html  css  js  c++  java
  • BZOJ 3931 网络吞吐量(最短路+拆点最大流)

    3931: [CQOI2015]网络吞吐量

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 1607  Solved: 652
    [Submit][Status][Discuss]

    Description

     路由是指通过计算机网络把信息从源地址传输到目的地址的活动,也是计算机网络设计中的重点和难点。网络中实现路由转发的硬件设备称为路由器。为了使数据包最快的到达目的地,路由器需要选择最优的路径转发数据包。例如在常用的路由算法OSPF(开放式最短路径优先)中,路由器会使用经典的Dijkstra算法计算最短路径,然后尽量沿最短路径转发数据包。现在,若已知一个计算机网络中各路由器间的连接情况,以及各个路由器的最大吞吐量(即每秒能转发的数据包数量),假设所有数据包一定沿最短路径转发,试计算从路由器1到路由器n的网络的最大吞吐量。计算中忽略转发及传输的时间开销,不考虑链路的带宽限制,即认为数据包可以瞬间通过网络。路由器1到路由器n作为起点和终点,自身的吞吐量不用考虑,网络上也不存在将1和n直接相连的链路。

     

    Input

    输入文件第一行包含两个空格分开的正整数n和m,分别表示路由器数量和链路的数量。网络中的路由器使用1到n编号。接下来m行,每行包含三个空格分开的正整数a、b和d,表示从路由器a到路由器b存在一条距离为d的双向链路。 接下来n行,每行包含一个正整数c,分别给出每一个路由器的吞吐量。

     

    Output

    输出一个整数,为题目所求吞吐量。

     

    Sample Input

    7 10
    1 2 2
    1 5 2
    2 4 1
    2 3 3
    3 7 1
    4 5 4
    4 3 1
    4 6 1
    5 6 2
    6 7 1
    1
    100
    20
    50
    20
    60
    1

    Sample Output

    70

    HINT

     

     对于100%的数据,n≤500,m≤100000,d,c≤10^9

    题目链接:BZOJ 3931

    由于一个路由器视为一个点而不是一条边因此要把路由器$i$拆成$i$与$i+n$的一条边,容量为该路由器吞吐量,然后跑个最短路在遍历所有边,若d[v]-d[u]==e[i].dist则说明这条边在最短路上,把它加入网络中,嗯这样一来绝壁1A啊,然后就怀疑人生了,输出结果居然是1,又滚回去看了下题目数据发现很奇怪,为什么起始点的吞吐量只有1答案却有70,最后发现是“自身的吞吐量不用考虑”这句话的问题,所以将起点和终点的吞吐量变为无穷大即可,数组大小根据拆点范围和for的循环关系可以得到。对了linux下的longlong用lld,然后inf用longlong下的memset设定的inf即可,

    这题无穷大的值一定要设好,不然可能会WA

    代码:

    #include <stdio.h>
    #include <bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define LC(x) (x<<1)
    #define RC(x) ((x<<1)+1)
    #define MID(x,y) ((x+y)>>1)
    #define CLR(arr,val) memset(arr,val,sizeof(arr))
    #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
    typedef pair<int, int> pii;
    typedef long long LL;
    const double PI = acos(-1.0);
    const int N = 510;
    const int M = 100010;
    struct Edge
    {
        int to, nxt;
        LL dx;
        Edge() {}
        Edge(int To, int Nxt, LL Dx): to(To), nxt(Nxt), dx(Dx) {}
    };
    struct edge
    {
        int to, nxt;
        LL cap;
        edge() {}
        edge(int To, int Nxt, LL Cap): to(To), nxt(Nxt), cap(Cap) {}
    };
    
    Edge E[M << 1];
    edge e[(N + 2 * M) << 1];
    int head[N], h[N << 1], tot, rtot;
    int d[N << 1];
    LL dis[N];
    bitset<N>vis;
    LL pos[N];
    
    void init()
    {
        CLR(head, -1);
        CLR(h, -1);
        rtot = 0;
        tot = 0;
        CLR(dis, INF);
        vis.reset();
        CLR(pos, 0);
    }
    inline void addE(int s, int t, LL dx)
    {
        E[tot] = Edge(t, head[s], dx);
        head[s] = tot++;
    }
    inline void adde(int s, int t, LL cap)
    {
        e[rtot] = edge(t, h[s], cap);
        h[s] = rtot++;
        e[rtot] = edge(s, h[t], 0LL);
        h[t] = rtot++;
    }
    void spfa(int s)
    {
        queue<int>q;
        q.push(s);
        dis[s] = 0LL;
        vis[s] = true;
        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u] = false;
            for (int i = head[u]; ~i; i = E[i].nxt)
            {
                int v = E[i].to;
                if (dis[v] > dis[u] + E[i].dx)
                {
                    dis[v] = dis[u] + E[i].dx;
                    if (!vis[v])
                    {
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
        }
    }
    int bfs(int s, int t)
    {
        CLR(d, -1);
        d[s] = 0;
        queue<int>q;
        q.push(s);
        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            for (int i = h[u]; ~i; i = e[i].nxt)
            {
                int v = e[i].to;
                if (d[v] == -1 && e[i].cap > 0LL)
                {
                    d[v] = d[u] + 1;
                    if (v == t)
                        return 1;
                    q.push(v);
                }
            }
        }
        return ~d[t];
    }
    LL dfs(int s, int t, LL f)
    {
        if (s == t || !f)
            return f;
        LL ret = 0LL;
        for (int i = h[s]; ~i; i = e[i].nxt)
        {
            int v = e[i].to;
            if (d[v] == d[s] + 1 && e[i].cap > 0LL)
            {
                LL df = dfs(v, t, min<LL>(f, e[i].cap));
                if (df > 0LL)
                {
                    e[i].cap -= df;
                    e[i ^ 1].cap += df;
                    ret += df;
                    f -= df;
                    if (!f)
                        break;
                }
            }
        }
        if (!ret)
            d[s] = -1;
        return ret;
    }
    LL dinic(int s, int t)
    {
        LL ret = 0LL;
        while (bfs(s, t))
            ret += dfs(s, t, INF);
        return ret;
    }
    int main(void)
    {
        int n, m, a, b, i;
        LL dx;
        while (~scanf("%d%d", &n, &m))
        {
            init();
            LL inf = dis[0];
            for (i = 0; i < m; ++i)
            {
                scanf("%d%d%lld", &a, &b, &dx);
                addE(a, b, dx); //Em
                addE(b, a, dx); //Em
            }
            for (i = 1; i <= n; ++i)
                scanf("%lld", &pos[i]);
    
            spfa(1);
            pos[1] = pos[n] = inf;
            for (int u = 1; u <= n; ++u)
            {
                adde(u, u + n, pos[u]); //en
                for (int j = head[u]; ~j; j = E[j].nxt)
                {
                    int v = E[j].to;
                    if (dis[v] - dis[u] == E[j].dx)
                        adde(u + n, v, inf); //em*2
                }
            }
            printf("%lld
    ", dinic(1, n << 1));
        }
        return 0;
    }
  • 相关阅读:
    区别TPS QPS HPS RPS PV UV
    C/C++常用库及工具
    CentOS常用命令备忘
    PHP的学习--Traits新特性
    CentOS7创建本地YUM源的三种方法
    CentOS下iptables详解
    Linux备份压缩命令
    Nginx HTTPS功能部署实践
    Fuel 30 分钟快速安装OpenStack
    hadoop学习通过虚拟机安装hadoop完全分布式集群
  • 原文地址:https://www.cnblogs.com/Blackops/p/6337003.html
Copyright © 2011-2022 走看看