ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[Codeforces 1037E. Trips]

2019-06-01 17:55:29  阅读:322  来源: 互联网

标签:度数 int 无用 1037E Codeforces 有用 聚会 删去 Trips


题目大意:有n个人,m天,每天晚上都会有一次聚会,一个人会参加一场聚会当且仅当聚会里有至少k个人是他的朋友。每天早上都会有一对人成为好朋友,问每天晚上最多能有多少人参加聚会。朋友关系不满足传递性。

   相当于有n个点,进行m次加边操作,每次操作后附加一个询问,问最大点集的大小,使得点集中每个点的度数均大于等于k

 

题解:如果直接边加边询问可能比较麻烦,本着“正难则反”的原则,我们可以将题目转化为,初始有m条边,每次操作是先询问当前的答案,再删去一条边。

   现在我们就可以先考虑,如果给你m条边,问对应的答案是多少,如何求解。这里给出一个定义,称一个人(点)为无用的,当且仅当没有人会因为他参加了聚会而参加聚会,否则称这个人是有用的。对于朋友关系(边)同理,当且仅当没有人会因此朋友关系而加入聚会,这条边才被称为无用

   显然,一个度数小于k的点肯定是无用的,因为他的朋友不到k个,肯定不会去聚会,更不会有人因为他去聚会。接下来我们可以发现,这个点连出去的边也肯定是无用的,理由同上。那既然这些边是无用的了,我们就可以将这些边删去,对应的一些点的度数就会减少,就可能会产生新的“无用点”,这时候我们就要再将这些点以及有连接到这些点的边删去,直至剩下的所有点和边都是有用的。此时,将剩下的这些点全部拿去参加聚会肯定是满足条件的,因此答案就是剩下的点的个数。

   接下来考虑删边的情况,每次删边前先检索这条边是否还存在(即是否还是有用的),如果他已经被当做无用边删除了,则这次操作不会对答案产生影响,继续进行下一次操作。如果这条边还是有用的,则删去这条边,如果删去这条边导致了新的无用点的产生(即出现了度数小于k的点),则删除此点和相关的边,操作方法和预处理时一致。这样做m次之后再输出答案就好了。

 

代码中s表示有用点的集合,d[i]记录与i相连的有用边的终点的集合

#include<bits/stdc++.h>
using namespace std;
#define N 200001
int n,m,k,x[N],y[N],ans[N];
set<int>d[N],s;
queue<int>q;
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++)
      scanf("%d%d",&x[i],&y[i]),
      d[x[i]].insert(y[i]),
      d[y[i]].insert(x[i]);
    for(int i=1;i<=n;i++)
      if(d[i].size()<k)
        q.push(i);
    while(!q.empty())
      {
      int cur=q.front();q.pop();
      for(auto nxt:d[cur])
        {
        d[nxt].erase(cur);
        if(d[nxt].size()<k)
          q.push(nxt);
        }
      d[cur].clear();
      }
    for(int i=1;i<=n;i++)
      if(d[i].size()>=k)s.insert(i);
    for(int i=m;i>=1;i--)
      {
      ans[i]=s.size();
      if(d[x[i]].count(y[i]))
        {
        d[x[i]].erase(y[i]);
        d[y[i]].erase(x[i]);
        if(d[x[i]].size()<k)
          q.push(x[i]);
        if(d[y[i]].size()<k)
          q.push(y[i]);
        }
      while(!q.empty())
        {
        int cur=q.front();q.pop();
        for(auto nxt:d[cur])
          {
          d[nxt].erase(cur);
          if(d[nxt].size()<k)
            q.push(nxt);
            }
        d[cur].clear(),s.erase(cur);
        }
      }
    for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
}

 

标签:度数,int,无用,1037E,Codeforces,有用,聚会,删去,Trips
来源: https://blog.csdn.net/c_czl/article/details/90731298

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有