[CQOI2015]网络吞吐量(最短路+最大流)

Posted 吃花椒的妙酱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CQOI2015]网络吞吐量(最短路+最大流)相关的知识,希望对你有一定的参考价值。

题目链接

 

 思路:跑一遍最短路求出起点到每个点的最短距离,然后就可以去掉无关的边了,最后跑一遍最大流即可。

每个路由器的容量,点化为边,转化为边的最大流即可

有个坑点是输入会有重边,无语了

#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
using namespace std;
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define pb push_back
#define IOS ios::sync_with_stdio(false)
#define int long long
#define inf 1e18
typedef long long ll;
const int N=1e3+10;
const int M=2e5+10;
const int p = 100000;
int s,t,n,m;
int d[N];
int a[N];

int ans1;
int g[N][N];
struct ty
{
    int u,t,next,flow;
    bool operator < (const ty&p) const
    {
        return flow > p.flow;
    }
}edge[M];
int tot=1,head[N];
void add(int x ,int y, int flow)
{
    edge[++tot]={x,y,head[x],flow};
    head[x]=tot;
}
void ini()
{
    tot=1;
    mst(head,-1);
}
bool bfs(int t)
{
    mst(d,0);
    queue <int> q;
    q.push(s);
    d[s]=1;
    while( !q.empty() )
    {
        int x = q.front();
        q.pop();
        if( x==t ) return true;
        for(int i=head[x] ;i!=-1;i=edge[i].next)
        {
            int y = edge[i].t;
            if( edge[i].flow > 0 && !d[y] )
            {
                d[y] = d[x] + 1;
                q.push(y);
            }
        }
    }
    return false;
}
int dfs(int x ,int flow ,int t)
{
    if( x==t ) return flow;
    int sum=0;
    for(int i=head[x] ;i!=-1;i=edge[i].next)
    {
        int y = edge[i].t;
        if( d[y] == d[x] +1 && edge[i].flow>0 )
        {
            int temp = dfs(y,min(edge[i].flow , flow-sum),t);
            edge[i].flow -= temp;
            edge[i^1].flow += temp;
            sum += temp;
            if( sum == flow ) return flow;
        }
    }
    return sum;
}
int dis[N];
bool v[N];
void dij(int s ,int t)
{
    mst(dis,0x3f);
    priority_queue <ty> q;
    q.push({0,s,0,0});
    dis[s]=0;
    while( !q.empty() )
    {
        ty x = q.top();
        q.pop();
        if( v[x.t] ) continue;
        v[x.t]=1;
        for(int i=head[x.t] ;i!=-1 ;i=edge[i].next)
        {
            int y = edge[i].t;
            int len = edge[i].flow;
            if( dis[y] > dis[x.t] + len )
            {
                dis[y] = dis[x.t] + len;
                q.push({0,y,0,dis[y]});
            }
        }

    }
}
signed main()
{
    ///!!!
//    freopen("data.txt","r",stdin);
    //!!!=
    IOS;
    ini();
    cin>>n>>m;
    _for(i,1,m)
    {
        int x,y,z;cin>>x>>y>>z;
        add(x,y,z);
        add(y,x,z);
        //nmd还会有重边,无语了
        if( !g[x][y]) g[x][y] = g[y][x]= z;
        else g[x][y] = g[y][x]= min(g[x][y],z);
    }
    dij(1,n);
    ini();
    _for(i,1,n)
    {
        int w;cin>>w;
        if( i==1 || i==n ) w=inf;//起点终点无限流量
        add(i,i+n,w);//化点为边
        add(i+n,i,0);
        _for(j,i+1,n)
        {
            if( dis[i] + g[i][j] == dis[j] && g[i][j] )//是最短路
            {
                add(i+n,j,inf),add(j,i+n,0);
            }
            if( dis[j] + g[i][j] == dis[i] && g[i][j] )//是最短路
            {
                add(j+n,i,inf),add(i,j+n,0);
            }
        }
    }
    int ans=0;
    s=1,t=2*n;//起点终点
    while( bfs(t) ) ans += dfs(s,inf,t);
    cout<<ans<<endl;
}

以上是关于[CQOI2015]网络吞吐量(最短路+最大流)的主要内容,如果未能解决你的问题,请参考以下文章

[CQOI2015]网络吞吐量(最短路+最大流)

luogu P3171 [CQOI2015]网络吞吐量 |网络流最大流

luogu P3171 [CQOI2015]网络吞吐量 |网络流最大流

BZOJ-3931网络吞吐量 最短路 + 最大流

网络吞吐量 [CQOI2015] [网络流]

[BZOJ 3931][CQOI2015]网络吞吐量(SPFA+网络流)