題目鏈接:https://vjudge.net/contest/180830#problem/C
題意:n個學生,老師想帶一部分學生出去但是又怕還有人發展爲情侶,滿足下列條件之一不會成爲情侶:(1)二人身高差大於40cm;(2)二人同性;(3)二人喜歡不同的音樂;(4)二人喜歡相同的運動。求老師最多可以帶多少人出去。
思路:在男女可能發展爲情侶的人之間建邊,求出該二分圖的最大匹配數,用總人數減去最大匹配數即可。
代碼如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstdlib>
#include<sstream>
#include<deque>
#include<stack>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-6;
const int maxn = 1000 + 20;
const int maxt = 300 + 10;
const int mod = 10;
const int dx[] = {1, -1, 0, 0};
const int dy[] = {0, 0, -1, 1};
const int Dis[] = {-1, 1, -5, 5};
const int inf = 0x3f3f3f3f;
const int MOD = 1000;
int n, m, k;
bool vis[maxn];
int match[maxn];
vector<int> g[maxn];
struct node{
int height;
string sex;
string music;
string sports;
void read(){
cin >> height >> sex >> music >> sports;
}
}num[maxn];
bool couple(node x, node y){//判斷是否可以成爲情侶
if(abs(x.height - y.height) > 40) return false;
if(x.sex == y.sex) return false;
if(x.music != y.music)return false;
if(x.sports == y.sports)return false;
return true;
}
bool dfs(int u){//尋找與u匹配的值
int v;
int len = g[u].size();
for(int i = 0; i < len; ++i){
v = g[u][i];
if(vis[v]) continue;
vis[v] = true;
if(match[v] == -1 || dfs(match[v])){
match[v] = u;
return true;
}
}
return false;
}
int main(){
int t;
scanf("%d", &t);
while(t--){
for(int i = 1; i < maxn; ++i) g[i].clear();
scanf("%d", &n);
for(int i = 1; i <= n; ++i){
num[i].read();
}
for(int i = 1; i <= n; ++i){
if(num[i].sex == "F") continue;//單向圖,男指向女
for(int j = 1; j <= n; ++j){
if(couple(num[i], num[j])){
g[i].push_back(j);
}
}
}
int cnt = 0;//最大匹配數
memset(match, -1, sizeof match);
for(int i = 1; i <= n; ++i){
memset(vis, 0, sizeof vis);
if(dfs(i)) ++cnt;
}
// cout << "CNT == " << cnt << endl;
printf("%d\n", n - cnt);
}
return 0;
}