BZOJ3931: [CQOI2015]网络吞吐量

Time Limit: 10 Sec  Memory Limit: 512 MB
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

Source

/**************************************************************

    Problem: 3931

    User: ictsing

    Language: C++

    Result: Accepted

    Time:568 ms

    Memory:8360 kb

****************************************************************/

 

//BZOJ3931 [CQOI2015]网络吞吐量

#include <iostream>

#include <cstdio>

#include <cstring>

#include <queue>

#include <cmath>

using namespace std;

typedef long long ll;

typedef pair<ll,ll> pa;

ll n,m;

const ll inf = 1e18;

const ll mt = 1000+5;

ll ecnt=0;

ll s,t;

const ll mm = 100000+5;

ll a[mm],b[mm],c[mm];

ll dx[4]={0,0,-1,1};

ll dy[4]={1,-1,0,0};

ll to[mm<<1],nxt[mm<<1],cap[mm<<1];

ll adj[mt],lev[mt],cur[mt],dis[mt];

void adde(ll u,ll v,ll ww)

{

    ecnt++,to[ecnt]=v,nxt[ecnt]=adj[u],cap[ecnt]=ww,adj[u]=ecnt;

}

void dk()

{

    priority_queue<pa,vector<pa>,greater<pa> >q;

    for(ll i=1;i<=n;i++) dis[i]=inf;

    dis[1]=0,q.push(make_pair(0,1));

    while(!q.empty())

    {

        ll u=q.top().second;q.pop();

        for(ll i=adj[u];i;i=nxt[i])

        {

            ll v=to[i];

            if(dis[u]+cap[i]<dis[v])

            {

                dis[v]=dis[u]+cap[i];

                q.push(make_pair(dis[v],v));

            }

        }

    }

}

queue<ll>q;

inline ll read()

{

    ll num=0,flag=1;

    char ch;

    do{

        ch=getchar();

        if(ch=='-') flag=-1;

    }while(ch<'0'||ch>'9');

    do{

        num=num*10+ch-'0';

        ch=getchar();

    }while(ch>='0'&&ch<='9');

    return num*flag;

}

bool bfs()

{

    while(!q.empty()) q.pop();

    memset(lev,-1,sizeof(lev));

    lev[s]=0,q.push(s);

    for(ll i=s;i<=t;i++) cur[i]=adj[i];

    while(!q.empty())

    {

        ll u=q.front();q.pop();

        for(ll i=adj[u];i;i=nxt[i])

        {

            ll v=to[i];

            if(lev[v]==-1&&cap[i])

            {

                lev[v]=lev[u]+1;

                q.push(v);

                if(v==t) return true;

            }

        }

    }

    return false;

}

ll dfs(ll u,ll flow)

{

    if(u==t||flow==0) return flow;

    ll delta,res=0;

    for(ll &i=cur[u];i;i=nxt[i])

    {

        ll v=to[i];

        if(cap[i]&&lev[v]==lev[u]+1)

        {

            delta=dfs(v,min(cap[i],flow-res));

            res+=delta,cap[i]-=delta,cap[i^1]+=delta;

            if(res==flow) return flow;

        }

    }

    if(res<flow) lev[u]=-1;

    return res;

}

ll maxflow()

{

    ll ans=0;

    while(bfs())

        ans+=dfs(s,inf);

    return ans;

}

int main()

{

    n=read(),m=read();

    for(ll i=1;i<=m;i++)

    {

        a[i]=read(),b[i]=read(),c[i]=read();

        adde(a[i],b[i],c[i]),adde(b[i],a[i],c[i]);

    }

    dk();

    memset(adj,0,sizeof(adj));ecnt=1;

    for(ll i=1;i<=m;i++)

    {

        if(dis[a[i]]+c[i]==dis[b[i]])

        {

            adde(a[i]+n,b[i],inf);

            adde(b[i],a[i]+n,0);

        }

        if(dis[b[i]]+c[i]==dis[a[i]])

        {

            adde(b[i]+n,a[i],inf);

            adde(a[i],b[i]+n,0);

        }

    }

    for(ll i=1;i<=n;i++)

    {

        ll c=read();

        if(i!=1&&i!=n) adde(i,i+n,c);

        else adde(i,i+n,inf);

        adde(i+n,i,0);

    }

    s=1,t=2*n;

    printf("%lld\n",maxflow());

    return 0;

}


评论

热度(7)