CF1105E Helping Hiasat

Posted huangchenyan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1105E Helping Hiasat相关的知识,希望对你有一定的参考价值。

最大独立集

神仙题,感觉不止2200的难度

先要建图

可以发现无论有多少个连续的1操作,都是可以看做1次1操作

那么可以将以这1作为分组的界限,将连续的2操作分为一组

然后将每一个朋友姓名的字符串用map哈希成数字

此时将每一个朋友在哪一组出现过都处理出来

称两个朋友是冲突的,当且仅当这两个朋友同时出现在任意一组中

那么将这两个朋友之间连边,那么图就建出来了

 

比赛时我就想到这里,然后用拓扑序乱搞,竟然水过了前29个点

后来jzy大佬,喊了一声最大独立集,我就恍然大悟

 

然后答案就是这张图的最大独立集

最大独立集就是原图补图的最大团

因为m是40的范围,直接暴力会超时,所以要有dp优化

MYY大佬是折半搜索的(好吧我不想写

当然,如果会高级算法也能直接过(然而我不会

#include <bits/stdc++.h>
#pragma GCC optimize(2)
#define ll long long
using namespace std;
const int MAXN=100000+10;
int n,m,w,si[51],vi[51],ans,g;
int MIN,fx[51][51],dp[51],s[51];
map <string,int> mp;
struct node

    int op;
    string name;
sh[MAXN];
vector <int> f[MAXN],ti[51],e[51];
set <pair<int,int> > q;
bool check(int x,int y)

    for (int i=0;i<(int)ti[x].size();i++)
    
        vector <int> :: iterator it;
        it=lower_bound(ti[y].begin(),ti[y].end(),ti[x][i]);
        if (it==ti[y].end())
          continue;
        if (*it==ti[x][i])
          return true;
    
    return false;

bool judge(int x,int end)

    for (int i=1;i<end;i++)
    
        if (!fx[s[i]][x])
          return false;
    
    return true;

void dfs(int x,int wh)//暴力求出补图的最大团

    if (x+m-wh+1<=ans || x+dp[wh]<=ans)
      return;
    for (int i=wh;i<=m;i++)
    
        if (judge(i,x+1))
        
            s[x+1]=i;
            dfs(x+1,i+1);
        
    
    if (x>ans)
      ans=x;

int main()

    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    
        scanf("%d",&sh[i].op);
        if (sh[i].op==2)
        
            cin>>sh[i].name;
            if (mp[sh[i].name]==0)
            
                w++;
                mp[sh[i].name]=w;//离散化
            
        
    
    int bl=-1;
    w=0;
    for (int i=1;i<=n;i++)//分组
    
        if (bl==-1 && sh[i].op==2)
        
            w++;
            bl=0;
            f[w].push_back(mp[sh[i].name]);
        
        else
        if (bl==0 && sh[i].op==2)
        
            f[w].push_back(mp[sh[i].name]);
        
        else
        if (bl==0 && sh[i].op==1)
          bl=-1;
    
    for (int i=1;i<=w;i++)
    
        for (int j=0;j<(int)f[i].size();j++)
          ti[f[i][j]].push_back(i);
    
    for (int i=1;i<=m;i++)
    
        for (int j=i+1;j<=m;j++)
        
            if (check(i,j))
            
                e[i].push_back(j);
                e[j].push_back(i);
            
        
    
    for (int i=1;i<=m;i++)
    
        for (int j=1;j<=m;j++)
          fx[i][j]=1;
    
    for (int i=1;i<=m;i++)
    
        for (int j=0;j<(int)e[i].size();j++)
          fx[i][e[i][j]]=0;//建出原图的补图
        fx[i][i]=0;
    
    dp[m]=1;
    ans=0;
    for (int i=m-1;i>=1;i--)//求出补图的最大团
    
        s[1]=i;
        dfs(1,i+1);
        dp[i]=ans;
    
    printf("%d\n",dp[1]);

 

以上是关于CF1105E Helping Hiasat的主要内容,如果未能解决你的问题,请参考以下文章

CF494C Helping People

[CF494C]Helping People

$CF1105E Helping Hiasat$ 最大团

Codeforces #282 div 1 C Helping People 题解

最大团&优化

E - Helping the HR Gym - 102040E