zoukankan      html  css  js  c++  java
  • BZOJ3931 [CQOI2015]网络吞吐量(DInic算法求最大流)

    Description

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

    Input

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

    Output

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

     

    题解:

    先按距离建图,用spfa跑一遍最短路径。

    建一个新图,每个点拆成两个点连边,容量为最大吞吐量,如果两个点之间的边在最短路径上,每个点的终点与另一个点的起点连边,跑Dinic算法求最大流。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll inf=1e18;
    const int maxn=1e6;
    int N,M;
    int head[maxn];
    int tol;
    struct node {
        int u;
        int v;
        ll w;
        int next;
    }edge[maxn];
    void addedge (int u,int v,ll w) {
        edge[tol].u=u;
        edge[tol].v=v;
        edge[tol].w=w;
        edge[tol].next=head[u];
        head[u]=tol++;
    } 
    ll d[maxn];
    int visit[maxn];
    void spfa (int s) {
        for (int i=1;i<=N;i++) d[i]=inf;
        d[s]=0;
        queue<int> q;
        q.push(s);
        visit[s]=1;
        while (!q.empty()) {
            int u=q.front();
            q.pop();
            visit[u]=0;
            for (int i=head[u];i!=-1;i=edge[i].next) {
                int v=edge[i].v;
                if (edge[i].w>0&&d[v]>d[u]+edge[i].w) {
                    d[v]=d[u]+edge[i].w;
                    if (!visit[v]) {
                        q.push(v);
                        visit[v]=1;
                    }
                }
            }
        }
    } 
    
    ll dep[maxn];
    ll inque[maxn];
    ll vi;
    ll cur[maxn];
    ll maxflow=0;
    int s,t;
    bool bfs () {
        for (int i=1;i<=2*N;i++) 
            cur[i]=head[i],dep[i]=inf,inque[i]=0;
        dep[s]=0;
        queue<int> q;
        q.push(s);
        while (!q.empty()) {
            int u=q.front();
            q.pop();
            inque[u]=0;
            for (int i=head[u];i!=-1;i=edge[i].next) {
                int v=edge[i].v;
                if (dep[v]>dep[u]+1&&edge[i].w) {
                    dep[v]=dep[u]+1;
                    if (inque[v]==0) {
                        q.push(v);
                        inque[v]=1;
                    }
                }
            }
        } 
        if (dep[t]!=inf) return 1;
        return 0;
    }
    
    ll dfs (int u,ll flow) {
        ll increase=0;
        if (u==t) {
            vi=1;
            maxflow+=flow;
            return flow;
        }
        ll used=0;
        for (int i=cur[u];i!=-1;i=edge[i].next) {
            cur[u]=i;
            int v=edge[i].v;
            if (edge[i].w&&dep[v]==dep[u]+1) {
                if (increase=dfs(v,min(flow-used,edge[i].w))) {
                    used+=increase;
                    edge[i].w-=increase;
                    edge[i^1].w+=increase;
                    if (used==flow) break;
                }
            }
        }
        return used;
    }
    
    
    ll Dinic () {
        while (bfs()) {
            vi=1;
            while (vi==1) {
                vi=0;
                dfs(s,inf);
            }
        }
        return maxflow;
    }
    int u[maxn];
    int v[maxn];
    ll w[maxn];
    int main () {
        memset(head,-1,sizeof(head));
        scanf("%d%d",&N,&M);
        for (int i=0;i<M;i++)  {
            scanf("%d%d%lld",&u[i],&v[i],&w[i]);
            addedge(u[i],v[i],w[i]);
            addedge(v[i],u[i],w[i]);
        }
        spfa(1);
        memset(head,-1,sizeof(head));
        tol=0;
        for (int i=0;i<M;i++) {
            if (d[u[i]]+w[i]==d[v[i]]) {
                addedge(u[i]+N,v[i],inf);
                addedge(v[i],u[i]+N,0);
            }
            if (d[v[i]]+w[i]==d[u[i]]) {
                addedge(v[i]+N,u[i],inf);
                addedge(u[i],v[i]+N,0);
            }
        }
        for (int i=1;i<=N;i++) {
            int c;
            scanf("%d",&c);
            if (i!=1&&i!=N) addedge(i,i+N,c);
            else addedge(i,i+N,inf);
            addedge(i+N,i,0);
        }
        s=1;
        t=2*N;
        printf("%lld
    ",Dinic());
    } 
  • 相关阅读:
    转:Backbone源码分析-Backbone架构+流程图
    PHP标记、
    虚拟机
    PHP学习的第一天
    对基础班的总结
    JS
    基础班学习总结
    react-router-dom
    vuecli3 自适应pc端界面
    vuecli内使用hotcss做移动端适配
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/12520497.html
Copyright © 2011-2022 走看看