当前位置: 代码迷 >> 综合 >> North American Southeast Regional 2019 (Div 1) D - Swap Free
  详细解决方案

North American Southeast Regional 2019 (Div 1) D - Swap Free

热度:25   发布时间:2024-01-26 08:39:23.0

D - Swap Free

题目链接:
题意:找一个集合的最大子集,这个集合中不允许互斥,两个字符串能相互转化(串字符交换一次变成另一个串)就算互斥。
思路:最大独立集

定义:选出一些顶点使得这些顶点两两不相邻,则这些点构成的集合称为独立集。找出一个包含顶点数最多的独立集称为最大独立集。

定理:最大独立集 = 所有顶点数 - 最小顶点覆盖 = 所有顶点数 - 最大匹配
就是最大独立集模板题,建好双向边,最后跑出来的匹配数应该是两个集合都跑了一遍匹配,结果cnt要?2

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=505;
char s[maxn][40];
vector<int>G[maxn];
int vis[maxn],matched[maxn],cnt=0,n,m,e;
bool Find(int u)
{for(int i=0; i<G[u].size(); i++){int v=G[u][i];if(vis[v])continue;vis[v]=1;if(!matched[v]||Find(matched[v])){matched[v]=u;return true;}}return false;
}
int Maxmatch()
{memset(matched,0,sizeof matched);for(int i=1; i<=n; i++){memset(vis,0,sizeof vis);if(Find(i))cnt++;}return cnt;
}
int main()
{scanf("%d",&n);for(int i=1; i<=n; i++){scanf("%s",s[i]);}int len=strlen(s[1]);for(int i=1; i<=n; i++){for(int j=i+1; j<=n; j++){int cnt1=0;for(int k=0; k<len; k++){if(s[i][k]!=s[j][k])cnt1++;}if(cnt1==2)G[i].push_back(j),G[j].push_back(i);}}printf("%d\n",n-Maxmatch()/2);
}