求最大独立集,一般图的最大独立集复杂度是指数的,要想到怎么构造二分图
由于每个字符串每个字符只出现一次(一开始没看到这个条件。。),所以可以按逆序对奇偶性来给点分组,构造二分图
构造出二分图后,最大独立集=n-最大匹配数
二分图匹配模板(O(nm)复杂度)
#include <bits/stdc++.h> using namespace std; const int N = 2e3 + 10; int n, m, e; vector<int> G[N]; //使用邻接表来储存边 int match[N], vis[N]; bool dfs(int u) { int len = G[u].size(); for (int i = 0; i < len; i++) { //遍历每一条边 int v = G[u][i]; if (vis[v]) continue; vis[v] = 1; if (!match[v] || dfs(match[v])) { //如果v没有匹配,或者v的匹配找到了新的匹配 match[v] = u; match[u] = v; //更新匹配信息 return 1; } } return 0; } int main() { scanf("%d %d %d", &n, &m, &e); for (int i = 1; i <= e; i++) { int a, b; scanf("%d %d", &a, &b); if (a > n || b > m) continue; G[a].push_back(n + b); G[n + b].push_back(a); } int ans = 0; for (int i = 1; i <= n; i++) { //对每一个点尝试匹配 for (int j = 1; j <= n + m; j++) vis[j] = 0; if (dfs(i)) ans++; } printf("%d", ans); return 0; }
本题代码
#include<bits/stdc++.h> using namespace std; #define N 505 char s[N][N]; vector<int>G[N],v1,v2; int n,vis[N],match[N]; int calc(char s[],char t[]){//s交换两个字符,和t匹配 int tot=0,c1[N]={},c2[N]={},len=strlen(s+1); for(int i=1;i<=len;i++) c1[s[i]-'a']++,c2[s[i]-'a']++; for(int i=0;i<26;i++) if(c1[i]!=c2[i])return 0; for(int i=1;i<=len;i++) if(s[i]!=t[i])tot++; if(tot==0 || tot==2)return 1; return 0; } bool dfs(int u){ for(auto v:G[u]){ if(vis[v])continue; vis[v]=1; if(!match[v] || dfs(match[v])){ match[v]=u; match[u]=v; return 1; } } return 0; } int main(){ cin>>n; for(int i=1;i<=n;i++)scanf("%s",s[i]+1); for(int i=1;i<=n;i++){ int sum=0,len=strlen(s[i]+1); for(int j=1;j<=len;j++) for(int k=j+1;k<=len;k++) if(s[i][j]>s[i][k])sum++; if(sum%2==0)v1.push_back(i); else v2.push_back(i); } for(auto u:v1) for(auto v:v2) if(calc(s[u],s[v])){ G[u].push_back(v); G[v].push_back(u); } int ans=0; for(auto u:v1){ memset(vis,0,sizeof vis); if(dfs(u))ans++; } cout<<n-ans<<' '; }