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

最短路 + 最大流 , 没什么好说的...

因为long long WA 了两次....

-------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<iostream>
 
#define rep( i , n ) for( int i = 0 ; i < n ; ++i )
#define clr( x , c ) memset( x , c , sizeof( x ) )
 
using namespace std;
 
typedef long long ll;
 
const ll INF = ( ll ) 1 << 60;
const int maxn = 1000 + 5;
 
struct edge {
int to;
ll cap;
edge *next , *rev;
};
 
edge* pt;
edge* head[ maxn ];
edge EDGE[ maxn * maxn ];
 
void init() {
pt = EDGE;
clr( head , 0 );
}
 
inline void add( int u , int v , ll d ) {
pt -> to = v;
pt -> cap = d;
pt -> next = head[ u ];
head[ u ] = pt++;
}
 
#define addEdge( u , v , d ) add( u , v , d ) , add( v , u , d )
 
inline void add_edge( int u , int v , ll d ) {
add( u , v , d );
add( v , u , 0 );
head[ u ] -> rev = head[ v ];
head[ v ] -> rev = head[ u ];
}
 
ll d[ maxn ];
 
void dijkstra( int n ) {
rep( i , n ) d[ i ] = INF;
d[ 0 ] = 0;
priority_queue< pair< ll , int > > Q;
Q.push( make_pair( 0 , 0 ) );
while( ! Q.empty() ) {
pair< ll , int > o = Q.top();
Q.pop();
int x = o.second;
ll dist = o.first;
if( dist != d[ x ] ) continue;
for( edge* e = head[ x ] ; e ; e = e -> next ) if( d[ e -> to ] > d[ x ] + e -> cap ) {
d[ e -> to ] = d[ x ] + e -> cap;
Q.push( make_pair( d[ e -> to ] , e -> to ) );
}
}
}
 
edge *p[ maxn ] , *cur[ maxn ];
int cnt[ maxn ] , h[ maxn ];
 
ll maxFlow( int S , int T , int N ) {
clr( cnt , 0 );
cnt[ S ] = N;
clr( h , 0 );
ll flow = 0 , A = INF;
int x = S;
edge* e;
while( h[ S ] < N ) {
for( e = head[ x ] ; e ; e = e -> next )
   if( h[ e -> to ] + 1 == h[ x ] && e -> cap > 0 ) break;
   
if( e ) {
p[ e -> to ] = cur[ x ] = e;
A = min( A , e -> cap );
x = e -> to;
if( x == T ) {
while( x != S ) {
p[ x ] -> cap -= A;
p[ x ] -> rev -> cap += A;
x = p[ x ] -> rev -> to;
}
flow += A;
A = INF;
}
} else {
if( ! --cnt[ h[ x ] ] ) break;
h[ x ] = N;
for( e = head[ x ] ; e ; e = e -> next ) if( e -> cap > 0 && h[ e -> to ] + 1 < h[ x ] ) {
h[ x ] = h[ e -> to ] + 1;
cur[ x ] = e;
}
cnt[ h[ x ] ]++;
if( x != S ) x = p[ x ] -> rev -> to;
}
}
return flow;
}
 
vector< int > U , V;
 
int main() {
int n , m;
cin >> n >> m;
init();
while( m-- ) {
int u , v , d;
scanf( "%d%d%d" , &u , &v , &d );
u-- , v--;
addEdge( u , v , d );
}
dijkstra( n );
U.clear();
V.clear();
rep( i , n )
for( edge* e = head[ i ] ; e ; e = e -> next ) 
   if(d[ e -> to ] == d[ i ] + e -> cap )
       U.push_back( i + n ) , V.push_back( e -> to );
       
init();
rep( i , n ) {
int v;
scanf( "%d" , &v );
i && i != n - 1 ? add_edge( i , i + n , v ) : add_edge( i , i + n , INF );
}
rep( i , V.size() )
   add_edge( U[ i ] , V[ i ] , INF );
   
cout << maxFlow( 0 , n * 2 - 1 , n * 2 ) << " ";
return 0;
}

  

-------------------------------------------------------------------------

3931: [CQOI2015]网络吞吐量

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

原文地址:https://www.cnblogs.com/JSZX11556/p/4531903.html