【模板】二分图匹配+构造+最大独立集——icpc PNWRC 2019

求最大独立集,一般图的最大独立集复杂度是指数的,要想到怎么构造二分图

由于每个字符串每个字符只出现一次(一开始没看到这个条件。。),所以可以按逆序对奇偶性来给点分组,构造二分图

构造出二分图后,最大独立集=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;
}
View Code

本题代码

#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<<'
';
} 
原文地址:https://www.cnblogs.com/zsben991126/p/12838674.html