POJ-1422 Bipartite Graph

General idea

Give a directed acyclic graph with n points and m edges. Let you send some paratroopers to land on certain points and walk through all the points. The paths of all paratroopers cannot overlap. That is, seek the least edge coverage.

theorem

Minimum edge coverage = number of points-maximum matching number of bipartite graph

analysis

Because the paths of each paratrooper cannot overlap, the maximum out-degree and in-degree of each point is 1. The
problem is simplified to select some edges so that the maximum out-degree and in-degree of all points is 1.
Because adding an edge You can save a paratrooper, so the answer = points-number of sides selected

Because the out-degree and in-degree can only be 1 or 0, they can correspond to matching and non-matching in the bipartite graph.
So separate the out-degree and in-degree of each point into two sets. Can do bipartite graph matching on two sets. The matched edge is the edge selected on the graph.

AC code

#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 200;
const int inf = 1e9;
#define fast ios::sync_with_stdio(false); cin.tie(0);cout.tie(0);

int G[maxn][maxn];
int vis[maxn], match[maxn];

int n, m;
int find(int x){
    
    
	for(int i = 1 ; i <= n ; i++){
    
    
		if(G[x][i] && !vis[i]){
    
    
			vis[i] = 1;
			if(match[i] == 0 || find(match[i])){
    
    
				match[i] = x;
				return 1;
			}
		}
	}
	return 0;
}

int main(){
    
    
	int T;
	cin >> T;
	while(T--){
    
    
		cin >> n >> m;

		memset(G, 0, sizeof G);
		memset(match, 0, sizeof match);
		int l, r;
		for(int i = 1 ; i <= m ; i++){
    
    
			cin >> l >> r;
			G[l][r] = 1;					
		}
		
		int ans = n;
		for(int i = 1 ; i <= n ; i++){
    
    
			for(int j = 1 ; j <= n ; j++)vis[j] = 0;
			ans -= find(i);
		}
		cout << ans << endl;
	}
}

Guess you like

Origin blog.csdn.net/qq_35068676/article/details/109629801