1. 程式人生 > 資訊 >我國“天問一號”環繞器成功實施第五次近火制動,進入遙感使命軌道

我國“天問一號”環繞器成功實施第五次近火制動,進入遙感使命軌道

二分圖

定義

二分圖,又稱二部圖,英文名叫 Bipartite graph。

二分圖是什麼?節點由兩個集合組成,且兩個集合內部沒有邊的圖。

換言之,存在一種方案,將節點劃分成滿足以上性質的兩個集合。

二分圖的性質:二分圖一定不存在長度為奇數的環

染色法判定是否為二分圖

思路分析:我們可以對每個點進行DFS並進行染色,如果存在一條邊的兩點顏色相同則說明不是二分圖。

程式碼示例:

//#pragma comment(linker,   "/STACK:10240000000000,10240000000000")
//#pragma GCC optimize(2)

#include <bits/stdc++.h>
using namespace std;

#define For(i,a,b) for (int i=(a);i<=(b);++i)
#define Fod(i,b,a) for (int i=(b);i>=(a);--i)
#define mls multiset
#define lb lower_bound
#define ub upper_bound
#define pb push_back
#define pob pop_back
#define itt iterator
#define endl '\n'
#define IOS ios::sync_with_stdio(0); cin.tie(0);
#define lowbit(x) x & (-x)
#define clr(x) memset(x, 0, sizeof(x));
#define fi first
#define se second

typedef vector<int> vii;
typedef vector<long long> vll;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
		
const int MAXN = 0x7fffffff;
const int MOD = 1000000007;
const ll MOD1 = 212370440130137957ll;

const int N = 1e5 + 5;
int h[N], e[2 * N], ne[2 * N], idx;
int color[N];
int n, m;

void add(int a, int b)
{
	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

bool dfs(int u, int c)
{
	color[u] = c;
	for(int i = h[u]; i != -1; i = ne[i]) //對點u的每條出邊進行染色
	{
		int j = e[i];
		if(!color[j]) //如果還沒有染色
		{
			if(!dfs(j, 3 - c)) return false; //如果染色失敗
		}
		else if(color[j] == c) return false; //如果兩點顏色相同
	}
	return true;
}

int main ()
{	
	//IOS;
	cin >> n >> m;
	memset(h, -1, sizeof h);

	for(int i = 1; i <= m; i ++)
	{
		int a, b;
		cin >> a >> b;
		add(a, b);
		add(b, a);
	}

	bool flag = true;

	for(int i = 1; i <= n; i ++)
		if(!color[i])
			if(!dfs(i, 1)) //dfs(i, c)表示對i進行dfs染色後是否成功
			{
				flag  = false;
				break;
			}
	if(flag) puts("Yes");
	else puts("No");

	return 0;
}	

二分圖最大匹配----匈牙利演算法

我們先將點歸為兩個集合,分別記為1和2

由於要找到最大匹配,我們只需對1進行遍歷向2匹配即可,不用對2再進行一遍同樣操作。對於每一個點,我們先遍歷他的所有出邊,隨後只要找到一個能匹配的就進行匹配,並用陣列記錄下來,但如果出邊的終點已經有匹配了,則就再去尋找出邊終點匹配的點(已用陣列記錄)是否有其他可匹配的點

程式碼示例:

//#pragma comment(linker,   "/STACK:10240000000000,10240000000000")
//#pragma GCC optimize(2)

#include <bits/stdc++.h>
using namespace std;

#define For(i,a,b) for (int i=(a);i<=(b);++i)
#define Fod(i,b,a) for (int i=(b);i>=(a);--i)
#define mls multiset
#define lb lower_bound
#define ub upper_bound
#define pb push_back
#define pob pop_back
#define itt iterator
#define endl '\n'
#define IOS ios::sync_with_stdio(0); cin.tie(0);
#define lowbit(x) x & (-x)
#define clr(x) memset(x, 0, sizeof(x));
#define fi first
#define se second

typedef vector<int> vii;
typedef vector<long long> vll;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
		
const int MAXN = 0x7fffffff;
const int MOD = 1000000007;
const ll MOD1 = 212370440130137957ll;

const int N = 505;
const int M = 1e5 + 5;

int n1, n2, m;
int h[N], ne[M], e[M], idx;
int match[N];
bool st[N];

void add(int a, int b)
{
	e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

bool find(int x)
{
	for(int i = h[x]; ~i; i = ne[i])
	{
		int j = e[i];
		if(st[j]) continue;//j這一輪已經匹配了
		st[j] = true;
		if(match[j] == 0 || find(match[j])) //match[j]存的是當前j的匹配物件
		{
			match[j] = x; //進行匹配
			return true;
		}	
	}
	return false;
}

int main ()
{	
	//IOS;
	cin >> n1 >> n2 >> m;
	memset(h, -1, sizeof h);
	for(int i = 1; i <= m; i ++)
	{
		int a, b;
		cin >> a >> b;
		add(a, b);
	}
	int res = 0;
	for(int i = 1; i <= n1; i ++)
	{
		memset(st, false, sizeof st); //每次都要初始化st,因為每一輪遍歷都有可能推翻之前的匹配
		if(find(i)) res ++;
	}
	cout << res << endl;	

	return 0;
}