• Codeforces Round #533 (Div. 2) E 最大独立集


    知识点

    最大独立集(set) = 补图的最大团(clique )

    最小顶点覆盖 + 最大独立集 = V

    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.
    • 2ss — 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 (1n105,1m401≤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.
    • 2ss — 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 Hiasat 可以修自己的id为任意值 

    2 Hiasat 得一个朋友查看id 

    当且仅当 他的朋友每次查看id都为自己的名字才是高兴的

    解析    很容易想到两个1之间的朋友是互斥的 只能使其中一名朋友高兴,我们在互斥的朋友之间连一条无向边,从而转化成求无向图的最大独立集问题。

    AC代码

      1 #include <bits/stdc++.h>
      2 #define pb push_back
      3 #define mp make_pair
      4 #define fi first
      5 #define se second
      6 #define all(a) (a).begin(), (a).end()
      7 #define fillchar(a, x) memset(a, x, sizeof(a))
      8 #define huan printf("
    ")
      9 #define debug(a,b) cout<<a<<" "<<b<<" "<<endl
     10 #define ffread(a) fastIO::read(a)
     11 using namespace std;
     12 const int maxn = 1e5+10;
     13 const int maxm = 1e4+10;
     14 const int inf = 0x3f3f3f3f;
     15 const int mod = 998244353;
     16 const double epx = 1e-6;
     17 typedef long long ll;
     18 const ll INF = 1e18;
     19 const double pi = acos(-1.0);
     20 //head------------------------------------------------------------------
     21 int G[100][100];
     22 int ans,cnt[100],group[100],n,m,vis[100];//ans表示最大团,cnt[N]表示当前最大团的节点数,group[N]用以寻找一个最大团集合
     23 map<string,int> pm;
     24 int tot = 0;
     25 struct node
     26 {
     27     int op;
     28     string s;
     29 } Q[maxn];
     30 vector<int> v;
     31 bool dfs(int u,int pos)//u为当从前顶点开始深搜,pos为深搜深度(即当前深搜树所在第几层的位置)
     32 {
     33     int i,j;
     34     for(i=u+1; i<=tot; i++) //按递增顺序枚举顶点
     35     {
     36         if(cnt[i]+pos<=ans)
     37             return 0;//剪枝
     38         if(G[u][i])
     39         {
     40             // 与目前团中元素比较,取 Non-N(i)
     41             for(j=0; j<pos; j++)
     42                 if(!G[i][vis[j]])
     43                     break;
     44             if(j==pos)
     45             {
     46                 // 若为空,则皆与 i 相邻,则此时将i加入到 最大团中
     47                 vis[pos]=i;//深搜层次也就是最大团的顶点数目,vis[pos] = i表示当前第pos小的最大团元素为i(因为是按增顺序枚举顶点 )
     48                 if(dfs(i,pos+1))
     49                     return 1;
     50             }
     51         }
     52     }
     53     if(pos>ans)
     54     {
     55         for(i=0; i<pos; i++)
     56             group[i] = vis[i]; // 更新最大团元素
     57         ans = pos;
     58         return 1;
     59     }
     60     return 0;
     61 }
     62 void maxclique()//求最大团
     63 {
     64     ans=-1;
     65     for(int i=tot; i>0; i--)
     66     {
     67         vis[0]=i;
     68         dfs(i,1);
     69         cnt[i]=ans;
     70     }
     71 }
     72 int main()
     73 {
     74     scanf("%d%d",&n,&m);
     75     for(int i=1; i<=n; i++)
     76     {
     77         int op;
     78         string tmp;
     79         scanf("%d",&op);
     80         if(op==1)
     81             Q[i].op = op;
     82         else
     83         {
     84             cin>>tmp;
     85             Q[i].op = op;
     86             Q[i].s = tmp;
     87             if(!pm[tmp])
     88                 pm[tmp] = ++tot;
     89         }
     90     }
     91     memset(G,inf,sizeof(G));
     92     Q[n+1].op=1;
     93     for(int i=1; i<=n+1; i++)
     94     {
     95         if(Q[i].op==1)
     96         {
     97             for(int j=0; j<v.size(); j++)
     98             {
     99                 for(int k=j+1; k<v.size(); k++)
    100                 {
    101                     G[v[k]][v[j]] = 0;
    102                     G[v[j]][v[k]] = 0;
    103                 }
    104             }
    105             v.clear();
    106         }
    107         else
    108         {
    109             v.push_back(pm[Q[i].s]);
    110         }
    111     }
    112     maxclique();
    113     if(ans<0)
    114         ans = 0;
    115     printf("%d
    ",ans);
    116     return 0;
    117 }
  • 相关阅读:
    JVM如何执行方法调用
    JVM如何实现反射
    JVM是如何处理异常的
    Java类加载
    windows-Kafka安装
    Google Eventbus简单使用
    队列c#版
    python 元类

    Spring Mvc 笔记二之异常和文件上传
  • 原文地址:https://www.cnblogs.com/stranger-/p/10303576.html
Copyright © 2020-2023  润新知