test 190801 codeforces 1037E Trips

简述题意:

给一幅图,边从 0 开始每天多一条边,问每天增加边之后能够有多少人去旅游。能去旅游的定义是只有当联通的点的度数都大于等于 k 才能去旅游,否则都不能去旅游。

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


这一题正向考虑不好做,反过来想,若果是从最后一天开始,不断删除边,就会简单很多
首先假设所有人都会去,然后去掉入度小于k的点,并删去相关的边,然后再找到入度小于k的点,删去相关边......
用一个类似拓扑排序的过程解决

#include<bits/stdc++.h>
using namespace std;
const int N=2*(1e5+5);
int n,m,k;
vector<int> to[N];
struct edge
{
    int a,b;
    bool del;
}e[N];
bool vis[N];
int deg[N],ans,f[N];
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;++i)
    {
        scanf("%d%d",&e[i].a,&e[i].b);
        ++deg[e[i].a],++deg[e[i].b];
        to[e[i].a].push_back(i);
        to[e[i].b].push_back(i);
        e[i].del=0;
    }
    ans=n;
    queue<int> q;
    for(int i=1;i<=n;++i)
        if(deg[i]<k) {q.push(i);--ans,vis[i]=1;}
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int i=0;i<to[u].size();++i)
        {
            int y=to[u][i],v=(e[y].a==u)?e[y].b:e[y].a;
            if(e[y].del) continue;
            --deg[v],--deg[u],e[y].del=1;
            if(deg[v]<k && !vis[v]) {q.push(v);--ans,vis[v]=1;}
        }
    }
    for(int i=m;i>=1;--i)
    {
        f[i]=ans;
        if(e[i].del) continue;
        e[i].del=1,--deg[e[i].a],--deg[e[i].b];
        if(deg[e[i].a]<k && !vis[e[i].a]) {q.push(e[i].a);--ans,vis[e[i].a]=1;}
        if(deg[e[i].b]<k && !vis[e[i].b]) {q.push(e[i].b);--ans,vis[e[i].b]=1;}
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int j=0;j<to[u].size();++j)
            {
                int y=to[u][j],v=(e[y].a==u)?e[y].b:e[y].a;
                if(e[y].del) continue;
                --deg[v],--deg[u],e[y].del=1;
                if(deg[v]<k && !vis[v]) {q.push(v);--ans,vis[v]=1;}
            }
        }
    }
    for(int i=1;i<=m;++i) printf("%d\n",f[i]);
    return 0;
}


猜你喜欢

转载自www.cnblogs.com/w19567/p/11282584.html