codeforces 1037E .Trips

本文介绍了一个基于图论的算法,用于解决特定的旅行计划问题。该问题要求在建立友谊关系的人群中,找出每天晚上能够满足特定条件的最大旅行团体人数。算法通过逆向思考,从最后一天开始向前推算,逐步移除友谊边并更新可参与旅行的人数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意 :给你一个n,m,k。表示有n个人,有m天。现在他们要出去玩,在出去玩的这些人里每个的朋友要大于等于k人才能出去玩(当然朋友是不能传递的 比如a和b是好基友 a和c是好基友 但b和c是不是基友就不一定了)。一开始每个人都是没有朋友的,接下来m行 每行输入x和y,表示这一天x和y成为了好盆友。现在要输出m行 每行表示这一天最多能有多少人出去玩。

思路 :先来到最后一天第m天 ,相当于把全部边都连起来,再数一下能有多少人能一起出去,不能出去的就更新他的好基友的朋友数量。就这样一天天从后往前破坏一对对好基友,更新能有多少人能出去。。。。

  一对好基友,谁都不许走

友情数据 

Input

21 19 2
17 21
21 5
16 11
18 2
21 4
17 7
20 6
10 20
7 2
9 17
8 15
13 21
18 16
2 13
13 14
21 15
10 3
11 9
20 12

Output
0
0
0
0
0
0
0
0
0
0
0
0
0
5
5
5
5
9
9

There are nn persons who initially don't know each other. On each morning, two of them, who were not friends before, become friends.

We want to plan a trip for every evening of mm days. On each trip, you have to select a group of people that will go on the trip. For every person, one of the following should hold:

  • Either this person does not go on the trip,
  • Or at least kk of his friends also go on the trip.

Note that the friendship is not transitive. That is, if aa and bb are friends and bb and cc are friends, it does not necessarily imply that aa and cc are friends.

For each day, find the maximum number of people that can go on the trip on that day.

Input

The first line contains three integers nn, mm, and kk (2≤n≤2⋅105,1≤m≤2⋅1052≤n≤2⋅105,1≤m≤2⋅105, 1≤k<n1≤k<n) — the number of people, the number of days and the number of friends each person on the trip should have in the group.

The ii-th (1≤i≤m1≤i≤m) of the next mm lines contains two integers xx and yy (1≤x,y≤n1≤x,y≤n, x≠yx≠y), meaning that persons xx and yy become friends on the morning of day ii. It is guaranteed that xx and yy were not friends before.

Output

Print exactly mm lines, where the ii-th of them (1≤i≤m1≤i≤m) contains the maximum number of people that can go on the trip on the evening of the day ii.

Examples

input

4 4 2
2 3
1 2
1 3
1 4

output

0
0
3
3

input

5 8 2
2 1
4 2
5 4
5 2
4 3
5 1
4 1
3 2

output

0
0
0
3
3
4
4
5

input

5 7 2
1 5
3 2
2 5
3 4
1 2
5 3
1 3

output

0
0
0
0
3
4
4

Note

In the first example,

  • 1,2,31,2,3 can go on day 33 and 44.

In the second example,

  • 2,4,52,4,5 can go on day 44 and 55.
  • 1,2,4,51,2,4,5 can go on day 66 and 77.
  • 1,2,3,4,51,2,3,4,5 can go on day 88.

In the third example,

  • 1,2,51,2,5 can go on day 55.
  • 1,2,3,51,2,3,5 can go on day 66 and 77.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#include <cstdlib>
#include <cmath>
using namespace std;
const int manx = 2e5+50;
const long long BW = 1e6;
vector<int >mp[manx];///存边
map <long long,bool >pm; ///标记边 x y  [x*BW+y]
struct node
{
    int x,y;
} E[manx];
int dd[manx],n,m,k,sum,ss[manx];///dd当前连了几个点 ss存答案 sum 几人能出去
void update(int x)
{
    if(dd[x]<k&&dd[x]>0)
    {
        for(int i=0; i<mp[x].size(); i++)
        {
            if(pm[mp[x][i]*BW+x]==0)
            {
                dd[x]--;
                dd[mp[x][i]]--;
                pm[x*BW+mp[x][i]]=1;
                pm[mp[x][i]*BW+x]=1;
                if(dd[mp[x][i]]==k-1)
                {
                    sum--;
                    update(mp[x][i]);
                }
            }
        }
        return ;
    }
    if(dd[x]>=k)
    {
        return ;
    }
}
int main()
{
    ///freopen("xx.txt","r",stdin);
    /// freopen("2.txt","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1; i<=m; i++)
    {
        scanf("%d%d",&E[i].x,&E[i].y);
        mp[E[i].x].push_back(E[i].y);
        mp[E[i].y].push_back(E[i].x);
    }
    sum = 0;
    for(int i=1; i<=n; i++)
    {
        dd[i]=mp[i].size();
        if(dd[i]>=k)
            sum++;
    }
    for(int i=1; i<=n; i++)
    {
        if(dd[i]<k)
        {
            for(int j=0; j<mp[i].size(); j++)
            {
                if(pm[i*BW+ mp[i][j] ]==0)
                {
                    dd[i]--;
                    dd[mp[i][j]]--;
                    if(dd[mp[i][j]]==k-1)
                        sum--;
                    pm[i*BW+mp[i][j] ]=1;
                    pm[mp[i][j]*BW+i]=1;
                    update(mp[i][j]);
                }
            }
        }
    }
    for(int i=m; i>0; i--)
    {
        ss[i]=max(sum,0);
        if(sum<=0||pm[E[i].x*BW+E[i].y]==1)
        {
            continue ;
        }
        pm[E[i].x*BW+E[i].y]=1;
        pm[E[i].y*BW+E[i].x]=1;
        dd[E[i].x]--;
        if(dd[E[i].x]==k-1)
            sum--;
        update(E[i].x);
        dd[E[i].y]--;

        if(dd[E[i].y]==k-1)
            sum--;
        update(E[i].y);
    }
    for(int i=1; i<=m; i++)
        printf("%d\n",ss[i]);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值