[HDU][3416][Marriage Match IV][网络流]

先求出最短路径,然后用最短路径上的边构建一个新图,在新图上求最小割。

#include <iostream>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
using namespace std;

int const N= 1010, M= 200010;
int n, m;
int const inf= 0x7fffffff;
int res;

struct Node{
	Node(){}
	Node(int a,int b ):adj(a), wt(b) {}
	int adj, wt; };

struct cmp{
	bool operator()( Node a, Node b ){
		return a.wt> b.wt; }
};

vector<Node> mata[N], matb[N];
int S, T;

int dista[N], distb[N];

int dijks( int s, int t, int d[], vector<Node> mat[] ){
	for( int i= 0; i<= n; ++i ) d[i]= inf;
	d[s]= 0;
	
	priority_queue<Node, vector<Node>, cmp> que;
	que.push( Node( s, 0 ) );
	
	while( !que.empty() ){
		int u= que.top().adj, w= que.top().wt; que.pop();
		
		if( w!= d[u] ) continue;
		
		for( size_t i= 0; i< mat[u].size(); ++i ){
			int v= mat[u][i].adj, t= mat[u][i].wt;
			
			if( d[u]+ t< d[v] ){
				d[v]= d[u]+ t;
				que.push( Node( v, d[v] ) );
			}
		}
	}
	
	return d[t];
}

struct Edge{  
    int flow, adj;  
    Edge* next;  
}tb[M];  
  
Edge* mat[N], *Pre[N]; 
int cnt= -1;
  
inline Edge* reserve( Edge* p ){  
    return tb+ ( (p- tb)^ 1 );  
}  
  
inline void add( int u, int v, int c ){  
    ++cnt;  
    tb[cnt].adj= v; tb[cnt].flow= c; 
    tb[cnt].next= mat[u]; mat[u]= tb+ cnt;  
    ++cnt;  
    tb[cnt].adj= u; tb[cnt].flow= 0; 
    tb[cnt].next= mat[v]; mat[v]= tb+ cnt;  
}  
  
int que[M], ht[N], flag[N], path[N], head, tail;  
  
int bfs(){  
    que[0]= S; head= 0; tail= 0;  
    for( int i= 0; i<= n; ++i ) ht[i]= -1; ht[S]= 0;  
      
    while( head<= tail ){  
        int u= que[head++];  
          
        for( Edge* p= mat[u]; p; p= p->next )  
        if( ht[p->adj]== -1 && p->flow ){  
            ht[p->adj]= ht[u]+ 1;  
            que[++tail]= p->adj;  
        }  
    }  
    return ht[T]!= -1;  
}  
  
int dfs( int u, int flow ){  
    if( u== T ) return flow;  
      
    int tf= 0, f;  
    for( Edge* p= mat[u]; p; p= p->next )  
    if( ht[p->adj]== ht[u]+ 1 && p->flow && flow> tf &&  
        ( f= dfs( p->adj, min( p->flow, flow- tf ) ) ) ){  
        reserve( p )->flow+= f;  
        p->flow-= f;  
        tf+= f;  
    }  
      
    if( tf== 0 ) ht[u]= -1;  
    return tf;  
}  

void build(){
	cnt= -1;
	for( int i= 0; i<= n; ++i ) mat[i]= 0;
	
	for( int u= 1; u<= n; ++u )
	for( size_t i= 0; i< mata[u].size(); ++i ){
		int v= mata[u][i].adj, w= mata[u][i].wt;
		
		if( dista[u]+ w+ distb[v]== res ){
			add( u, v, 1 );
		}
	}
}

int main(){
	int test;
	scanf("%d",&test );
	while( test-- ){
		scanf("%d%d",&n,&m );
		
		for( int i= 0; i< m; ++i){
			int u, v, d;
			scanf("%d%d%d", &u, &v, &d );
			mata[u].push_back( Node(v,d) );
			matb[v].push_back( Node(u,d) );
		}
		scanf("%d%d", &S, &T );
		
		dijks( S, T, dista, mata );
		res= dijks( T, S, distb, matb );

		build();
		int ans= 0;
		while( bfs() ) ans+= dfs( S, 0x7fffffff );
		printf("%d\n", ans );
		
		for( int i= 0; i<= n; ++i )
		mata[i].clear(), matb[i].clear();
	}
	
	return 0;
}
 

你可能感兴趣的:(C++,c,F#,C#)