訓練指南 UVALive - 3415(最大點獨立集)
阿新 • • 發佈:2019-02-05
ring == out 就是 http title cin != 我們
layout: post
title: 訓練指南 UVALive - 3415(最大點獨立集)
author: "luowentaoaa"
catalog: true
mathjax: true
tags:
- 二分圖
- 圖論
- 訓練指南
Guardian of Decency
UVALive - 3415
我們將男女分開來 就可以建出一個二分圖,對於任意的男女生 只要上邊四個條件一個也不滿足 就表示不能同時去 ,那麽我們在其中間連一條邊,那麽最終的結果就是我們從中取出盡量多的點,使得任意兩個點之間沒有連線。那麽問題就轉化成了求最大點獨立集。 二分圖的最大點獨立集= 總點數 - 最大匹配(最小點覆蓋)
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=998244353; const int maxn=1e3+50; const ll inf=1e10; const ll INF = 1000000000; const double eps=1e-5; #define bug cout<<"bbibibibbbb="<<endl; /// 二分圖最大基數匹配 struct BPM{ int n,m; /// 左右頂點個數 int G[maxn][maxn]; /// 鄰接表 int left[maxn]; /// left[i]為右邊第i個點的匹配點編號,-1表示不存在 bool T[maxn]; /// T[i]為右邊第i個點是否已標記 int right[maxn]; /// 求最小覆蓋用 bool S[maxn]; /// 求最小覆蓋用 void init(int n,int m){ this->n=n; this->m=m; memset(G,0,sizeof(G)); } /* void AddEdge(int u,int v){ G[u].push_back(v); }*/ bool match(int u){ S[u]=true; for(int v=0;v<m;v++){ //int v=G[u][i]; if(G[u][v]&&!T[v]){ T[v]=true; if(left[v]==-1||match(left[v])){ left[v]=u; right[u]=v; return true; } } } return false; } /// 求最大匹配 int solve(){ memset(left,-1,sizeof(left)); memset(right,-1,sizeof(right)); int ans=0; for(int u=0;u<n;u++){ memset(S,0,sizeof(S)); memset(T,0,sizeof(T)); if(match(u))ans++; } return ans; } /// 求最小覆蓋。X和Y為最小覆蓋中的點集 int mincover(vector<int>& X,vector<int>& Y){ int ans=solve(); memset(S,0,sizeof(S)); memset(T,0,sizeof(T)); for(int u=0;u<n;u++) if(right[u]==-1)match(u); for(int u=0;u<n;u++) if(!S[u])X.push_back(u); for(int v=0;v<n;v++) if(T[v])Y.push_back(v); return ans; } }; BPM solver; struct node{ int h; string m,s; node(int h,string m,string s):h(h),m(m),s(s){} }; bool ok(node a,node b){ return abs(a.h-b.h)<=40&&a.m==b.m&&a.s!=b.s; } int R,C,N; int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); int t; cin>>t; while(t--){ int n; cin>>n; vector<node>a,b; for(int i=0;i<n;i++){ int h;string m,s,sex; cin>>h>>sex>>m>>s; if(sex[0]=='M')a.push_back(node(h,m,s)); else b.push_back(node(h,m,s)); } int x=a.size(),y=b.size(); solver.init(x,y); for(int i=0;i<x;i++) for(int j=0;j<y;j++) if(ok(a[i],b[j]))solver.G[i][j]=1; cout<<x+y-solver.solve()<<endl; } return 0; }
訓練指南 UVALive - 3415(最大點獨立集)