Codeforces Round #533 (Div. 2) E. Helping Hiasat

http://codeforces.com/contest/1105/problem/E

E. Helping Hiasat

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Hiasat registered a new account in NeckoForces and when his friends found out about that, each one of them asked to use his name as Hiasat's handle.

Luckily for Hiasat, he can change his handle in some points in time. Also he knows the exact moments friends will visit his profile page. Formally, you are given a sequence of events of two types:

  • 11 — Hiasat can change his handle.
  • 22 ss — friend ss visits Hiasat's profile.

The friend ss will be happy, if each time he visits Hiasat's profile his handle would be ss.

Hiasat asks you to help him, find the maximum possible number of happy friends he can get.

Input

The first line contains two integers nn and mm (1≤n≤105,1≤m≤401≤n≤105,1≤m≤40) — the number of events and the number of friends.

Then nn lines follow, each denoting an event of one of two types:

  • 11 — Hiasat can change his handle.
  • 22 ss — friend ss (1≤|s|≤401≤|s|≤40) visits Hiasat's profile.

It's guaranteed, that each friend's name consists only of lowercase Latin letters.

It's guaranteed, that the first event is always of the first type and each friend will visit Hiasat's profile at least once.

Output

Print a single integer — the maximum number of happy friends.

Examples

input

Copy

5 3
1
2 motarack
2 mike
1
2 light

output

Copy

2

input

Copy

4 3
1
2 alice
2 bob
2 tanyaromanova

output

Copy

1

Note

In the first example, the best way is to change the handle to the "motarack" in the first event and to the "light" in the fourth event. This way, "motarack" and "light" will be happy, but "mike" will not.

In the second example, you can choose either "alice", "bob" or "tanyaromanova" and only that friend will be happy.

 

题目大意:有m个人,n组询问,每次询问若为1,则可以将当前账户名字更改,若为2,则再输入一个人的名字,第一次输入一定为1,问最多能让多少个人开心(及每次输入2后的那个人的名字和当前账户名字一样,那个人就是开心的)

解:可以将每个人名和一个数字对应,每两个1之间的人不可能同时开心(包括最后一个1后的人),那么在不可能同时开心的人之间连一条无向边,问题就转化成了求无向图中的最大点独立集的大小,而最大点独立集和补图中最大完全子图相同,就可以直接dfs将最大完全子图跑出来(图中只有40个点)

代码1:

#include <bits/stdc++.h>
using namespace std;
bool maps[45][45];
vector<int> best;
vector<int> now;
int ans;
int n;
void dfs(int pos){
    if(pos==n+1){
        if(now.size()>best.size()){
            best=now;
            ans=1;
        } else if(now.size()==best.size()){
            best=now;
            ans++;
        }
        return;
    }
    bool flag=true;
    for(int i=0;i<now.size();i++){
        int nxt=now[i];
        if(!maps[pos][nxt]){
            flag=false;
            break;
        }
    }
    if(now.size()+(n-pos)>=best.size()){
        if(flag){
            now.push_back(pos);
            dfs(pos+1);
            now.pop_back();
        }
        dfs(pos+1);
    }
}

int main() {
    int m;
    scanf("%d%d",&m,&n);
    int cnt = 0,opt;
    string s;
    map<string,int> ma;
    set<int> se;
    set<int>::iterator it1,it2;
    for(int i = 1;i <= n;++i)
        for(int j = 1;j <= n;++j)
            maps[i][j] = 1;
    for(int i = 1;i <= m;++i)
    {
        scanf("%d",&opt);
        if(opt == 1)
        {
            for(it1 = se.begin(); it1 != se.end();++it1)
                for(it2 = se.begin(); it2 != se.end();++it2)
                        maps[*it1][*it2] = 0;
            se.clear();
        }
        else
        {
            cin >> s;
            if(ma.find(s) != ma.end())
                se.insert(ma[s]);
            else
            {
                ma[s] = ++cnt;
                se.insert(cnt);
            }
        }
    }
    for(it1 = se.begin(); it1 != se.end();++it1)
                for(it2 = se.begin(); it2 != se.end();++it2)
                        maps[*it1][*it2] = 0;
        dfs(1);
        cout<<best.size();
        return 0;
}

 

代码2:

#include <bits/stdc++.h>
using namespace std;
int some[130][130];//±ðÓÃSTLÁË£¬ÕâÌâÀï¾ÍÄÜÊ¡Ò»°ë»¹¶àµÄʱ¼äÁË
int all[130][130];//ÕâÀïµÄÊý×éÈçÉÏËùÊö
int none[130][130];
int maps[130][130];//ÁÚ½Ó¾ØÕó£¬ÅжÏÓÐûÓбßÏàÁ¬ÊÇO(1)µÄ±È½Ï·½±ã
int degrees[130];//¼Ç¼¸÷¸ö½ÚµãµÄ¶ÈÊý
int ans;
bool cmp(int a,int b){
    return degrees[a]>degrees[b];//¸ù¾Ý¶ÈÊýÅÅÐò£¬¶ÈÊý×î´óµÄ¿ÉÒÔ×÷Ϊpivotµã
}
void BronKerbosch(int pos,int al,int so,int no){
    if(so==0 && no==0){
        ans = max(ans,al);//ÕâÀïµÄall[pos]¼´ÎªÎÒÃǼ«´óÍÅ£¬ÒªÇó×î´óÍÅÖ»ÐèÒª±È½ÏÒ»ÏÂal´óС¼´¿É¡£
        return;
    }
    int pivot;
    if(so!=0){
        pivot=some[pos][0];//ÅŹýÐòÁË£¬ËùÒÔµ±Ç°some¼¯ºÏµÄµÚÒ»¸öÔªËØÊǶÈÊý×î´óµÄµã
        for(int i=0;i<al;i++)
            all[pos+1][i]=all[pos][i];//´Ó±¾²ã³ö·¢µÄ±éÀúall¼¯ºÏµÄÇ°ÃæÔªËض¼ÊǺͱ¾²ãÒ»ÑùµÄ
    }
    for(int i=0; i<so; i++){
        int nxt=some[pos][i];
        if(maps[pivot][nxt])
            continue;//pivotÓÅ»¯£¬pivotµÄÁڽӵ㲻¼ì²é
        int nso=0,nno=0;//ÏÂÒ»²ãsome¼¯ºÏµÄ´óС£¬ÏÂÒ»²ãnone¼¯ºÏµÄ´óС
        all[pos+1][al]=nxt;//°Ñµ±Ç°µ÷²éµã¼ÓÈëµ½ÏÂÒ»²ãµÄall¼¯ºÏÖÐ
        for(int j=0; j<so; j++)
            if(maps[nxt][some[pos][j]] && some[pos][j]!=-1)//ÇóºÍÁÚ½ÓµãµÄ½»¼¯
                some[pos+1][nso++]=some[pos][j];
        for(int j=0; j<no; j++)
            if(maps[nxt][none[pos][j]])//ÇóºÍÁÚ½ÓµãµÄ½»¼¯
                none[pos+1][nno++]=none[pos][j];
        BronKerbosch(pos+1,al+1,nso,nno);
        some[pos][i]=-1;none[pos][no++]=nxt;//´ÓsomeÖÐÒƳýÒѾ­µ÷²é¹ýµÄµã²¢ÒÆÈënone
    }
}
int main(){
    int n,m;
    scanf("%d%d",&m,&n);
    int cnt = 0,opt;
    string s;
    map<string,int> ma;
    set<int> se;
    set<int>::iterator it1,it2;
    for(int i = 1;i <= n;++i)
        for(int j = 1;j <= n;++j)
            maps[i][j] = 1;
    for(int i = 1;i <= m;++i)
    {
        scanf("%d",&opt);
        if(opt == 1)
        {
            for(it1 = se.begin(); it1 != se.end();++it1)
            {
                degrees[*it1] += se.size();
                for(it2 = se.begin(); it2 != se.end();++it2)
                    maps[*it1][*it2] = 0;
            }
            se.clear();
        }
        else
        {
            cin >> s;
            if(ma.find(s) != ma.end())
                se.insert(ma[s]);
            else
            {
                ma[s] = ++cnt;
                se.insert(cnt);
            }
        }
    }
    for(it1 = se.begin(); it1 != se.end();++it1)
    {
        degrees[*it1] += se.size();
        for(it2 = se.begin(); it2 != se.end();++it2)
            maps[*it1][*it2] = 0;
    }
    int so=0;
    for(int i=1;i<=n;i++)
           some[0][so++]=i;//Ò»¿ªÊ¼some¼¯ºÏÒª°üº¬ËùÓнڵã
    sort(some[0]+1,some[0]+n+1,cmp);
    ans=0;
    BronKerbosch(0,0,so,0);//Ò»¿ªÊ¼²ãÊýΪ0£¬allºÍnone¶¼Îª¿Õ
    printf("%d",ans);
    return 0;
}

    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值