BZOJ3931 CQOI2015 网络吞吐量

3931: [CQOI2015]网络吞吐量

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 2083  Solved: 870
[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

 

Source

先跑出最短路,然后依据条件建图即可,最后跑出最大流即可

#include <bits/stdc++.h>
#define ll long long
#define inf 1000000000007
using namespace std;
inline int read(){
    int x=0;int f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int MAXN=2e5+10;
struct node{
    int x,y,next;
    ll v;
}e[MAXN<<1];
int linkk[MAXN<<1],len=0,n,m,dis[MAXN],vis[MAXN],a[MAXN],b[MAXN],d[MAXN],qq[MAXN],head,tail,level[2000];
typedef pair <int,int> pii;
priority_queue < pii,vector<pii>,greater<pii> > q; 
inline void insert(int xx,int yy,ll vv){
    e[++len].y=yy;e[len].v=vv;e[len].next=linkk[xx];linkk[xx]=len;
}
void dijsktra(){
    memset(dis,127,sizeof(dis));
    q.push(make_pair(0,1));
    dis[1]=0;
    while(!q.empty()){
        int tn=q.top().second;q.pop();
        if(vis[tn]) continue;
        vis[tn]=1;
        for(int i=linkk[tn];i;i=e[i].next){
            if(dis[tn]+e[i].v<dis[e[i].y]){
                dis[e[i].y]=dis[tn]+e[i].v;
                q.push(make_pair(dis[e[i].y],e[i].y));
            }
        }
    }
}
namespace zhangenming{
    inline bool getlevel(){
        memset(level,-1,sizeof(level));
        head=tail=0;
        qq[++tail]=1;level[1]=0;
        while(head<tail){
            int tn=qq[++head];
            for(int i=linkk[tn];i;i=e[i].next){
                if(level[e[i].y]==-1&&e[i].v){    
                    level[e[i].y]=level[tn]+1;
                    qq[++tail]=e[i].y;
                }
            }
        }
        return level[2*n]!=-1;
    }
    inline ll getmaxflow(int st,ll flow){
        if(st==2*n) return flow;
        ll d,maxflow=0;
        for(int i=linkk[st];i&&maxflow<flow;i=e[i].next){
            if(level[e[i].y]==level[st]+1&&e[i].v>0){
                d=getmaxflow(e[i].y,min(e[i].v,flow-maxflow));
                e[i].v-=d;
                if(i%2==0) e[i-1].v+=d;
                else e[i+1].v+=d;
                maxflow+=d;
            }
        }
        if(!maxflow) level[st]=-1;
        return maxflow;
    }
    int dinic(){
        ll ans=0;ll sum;
        while(getlevel()){
            sum=getmaxflow(1,inf); ans+=sum;
        }
        cout<<ans<<endl;
    }
    void init(){
        n=read();m=read();
        for(int i=1;i<=m;i++){
            a[i]=read();b[i]=read();d[i]=read();
            insert(a[i],b[i],d[i]);
            insert(b[i],a[i],d[i]);
        }
        dijsktra();
        len=0;
        memset(linkk,0,sizeof(linkk));
        for(int i=1;i<=m;i++){
            if(dis[a[i]]+d[i]==dis[b[i]]) insert(a[i]+n,b[i],inf),insert(b[i],a[i]+n,0);
            if(dis[b[i]]+d[i]==dis[a[i]]) insert(b[i]+n,a[i],inf),insert(a[i],b[i]+n,0);
        }
        for(int i=1;i<=n;i++){
            int vv=read();
            if(i!=1&&i!=n) insert(i,i+n,vv);
            else insert(i,i+n,inf);
            insert(i+n,i,0);
        }
        dinic();
    }
}
int main(){
    using namespace zhangenming;
    init();
    return 0;
}

  

 

posted @ 2017-12-12 21:38  zhangenming  阅读(170)  评论(0编辑  收藏  举报