[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]网络吞吐量(最短路+最大流)的主要内容,如果未能解决你的问题,请参考以下文章
luogu P3171 [CQOI2015]网络吞吐量 |网络流最大流