题解:CF1037E Trips
William2022 · · 题解
CF1037E
入手
先考虑将问题简化, 如果只要求一天晚上的人数怎么做?
答案:重复将所有度数小于
不难看出这是一个改版的拓扑排序。
解法
通过这样的方法,我们就可以先求出最后一天的旅行人数。
考虑从
每次删边的时候,将连接的两个点度数减一。
程序设计
拓扑排序需要简单修改
我这边删除边是邻接表硬删(第
我使用了函数 qingtui(x) 来删除一个点并加入拓扑的队列
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
vector<int> to[N];
struct Edge{int u,v;}e[N];
int n,m,k,ans;
int d[N];// 度数
bool del[N];
queue<int> q;// 拓扑排序
void qingtui(int x){
q.push(x);
ans--;
del[x]=1;
}
void topo(){
while(!q.empty()){
int u=q.front(); q.pop();
for(int v:to[u]){
if(!del[v] && (--d[v])<k){
qingtui(v);
}
}
}
}
signed main(){
ios::sync_with_stdio(false); cin.tie(0);
cin>>n>>m>>k;
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
e[i]={u,v};
to[u].push_back(v);
to[v].push_back(u);
}
for(int i=1;i<=m;i++)d[e[i].u]++, d[e[i].v]++;
ans=n;
for(int i=1;i<=n;i++)if(d[i]<k)qingtui(i);
topo();
vector<int> output;
output.push_back(ans);
for(int i=m;i>=2;i--){
int u=e[i].u, v=e[i].v;
to[u].pop_back(); to[v].pop_back();
if(!(del[u]||del[v])){// 这条边还没被拓扑排序删除掉
if((--d[u])<k)qingtui(u);
if((--d[v])<k)qingtui(v);
topo();
}
output.push_back(ans);
}
reverse(output.begin(),output.end());
for(int x:output)cout<<x<<"\n";
}