洛谷P1231 教辅的组成 网络流简单拆点

P1231

建图:
因为一本书只能用一次,所以将书拆点为1 , 2
s -> 练习册 - > 书1 - > 书2 -> 答案 - > t
流量都为1
Code:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 6e5 + 66 ; 
const int N = 10000 ; 
int s = 0 , t = 10 * N ; 
int head[AX] ;
int d[AX] ; 
int cur[AX] ; 
int tot ; 
struct Node{
	int u , v , flow , next1 ; 
	Node( int u = 0 , int v = 0 , int flow = 0 , int next1 = 0 ):u(u),v(v),flow(flow),next1(next1){}
}G[AX*10];
void addEdge( int u , int v , int w ){
	G[tot] = Node( u , v , w , head[u] ) ; head[u] = tot++ ;
	G[tot] = Node( v , u , 0 , head[v] ) ; head[v] = tot++ ;
}

bool bfs(){
	memset( d , -1 , sizeof(d) ) ;
	d[s] = 0 ;
	queue<int>q;
	q.push(s);
	while( !q.empty() ) {
		int u = q.front() ; 
		q.pop() ; 
		for( int i = head[u] ; ~i ; i = G[i].next1 ) {
			int v = G[i].v ; 
			if( d[v] == -1 && G[i].flow ){
				d[v] = d[u] + 1 ; 
				q.push(v) ;
				if( v == t ) return true;
			}
		}
	}
	return ~d[t] ; 
}
int dfs( int u , int cap ){
	if( u == t || !cap ) return cap ; 
	int r = 0 ;
	for( int i = cur[u] ; ~i ; i = G[i].next1 ){
		int v = G[i].v ;
		if( G[i].flow && d[v] == d[u] + 1 ){
			int tmp = min( G[i].flow , cap - r ) ;
			cur[u] = i ; 
			tmp = dfs( v , tmp );
			r += tmp ;
			G[i].flow -= tmp ; 
			G[i^1].flow += tmp ; 
			if( r == cap ) break ;
		}
	}
	if( !r ) d[u] -= 2 ; 
	return r ; 
}

int Dinic(){
	int cnt = 0 ;
	int tmp ; 
	while( bfs() ){
		memcpy( cur , head , sizeof(head) ) ;
		while( tmp = dfs( s , INF ) ) cnt += tmp ; 
	}
	return cnt ;
}
int main(){
	int n1 , n2 , n3 ;
	int m1 , m2 ;  
	int x , y ; 
	tot = 0 ; 
	memset( head , -1 , sizeof(head) ) ;
	scanf("%d%d%d",&n1,&n2,&n3) ;
	for( int i = 1 ; i <= n2 ; i++ ){
		addEdge( s , i + 2 * N , 1 ) ; 
	}
	scanf("%d",&m1) ; 
	for( int i = 0 ; i < m1 ; i++ ){
		scanf("%d%d",&x,&y) ; 
		addEdge( y + 2 * N , x , 1 ) ; 
	}
	for( int i = 1 ; i <= n1 ; i ++ ){
		addEdge( i , i + N , 1 ) ; 
	}
	scanf("%d",&m2) ;
	for( int i = 0 ; i < m2 ; i++ ){
		scanf("%d%d",&x,&y) ; 
		addEdge( x + N , y + 3 * N , 1 ) ;
	}
	for( int i = 1 ; i <= n3 ; i++ ){
		addEdge( i + 3 * N , t , 1 ) ; 
	}
	printf("%d\n",Dinic());
	return 0 ; 	
}

猜你喜欢

转载自blog.csdn.net/FrankAx/article/details/84882298