[CF1037E] Trips

题目传送门

这道题正着做有点难办,我们考虑倒序处理。

先把所有的边连在一起,再一条一条删边。

每次把入度小于k的点都删掉就行了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 #define bro(i) ((i%2)?(i+1):(i-1))
 6 using namespace std;
 7 
 8 int n,m,k;
 9 int hd[200005],to[400005],nx[400005],ec;
10 int cp[200005][2];
11 bool de[400005];
12 int deg[200005];
13 int ans[200005];
14 int tot;
15 bool del[200005];
16 
17 void edge(int af,int at)
18 {
19     to[++ec]=at;
20     nx[ec]=hd[af];
21     hd[af]=ec;
22     deg[at]++;
23 }
24 
25 queue<int>qq;
26 
27 void split()
28 {
29     while(!qq.empty())
30     {
31         int p=qq.front();
32         qq.pop();
33         if(del[p])continue;
34         del[p]=1;
35         tot--;
36         for(int e=hd[p];e;e=nx[e])
37         {
38             if(de[e])continue;
39             int t=to[e];
40             deg[t]--;
41             if(deg[t]<k&&(!del[t]))
42             {
43                 qq.push(t);
44             }
45         }
46     }
47 }
48 
49 int main()
50 {
51     scanf("%d%d%d",&n,&m,&k);
52     for(int i=1;i<=m;i++)
53     {
54         scanf("%d%d",&cp[i][0],&cp[i][1]);
55         edge(cp[i][0],cp[i][1]);
56         edge(cp[i][1],cp[i][0]);
57     }
58     tot=n;
59     for(int i=1;i<=n;i++)
60         if(deg[i]<k)qq.push(i),split(); 
61     for(int i=m;i;i--)
62     {
63         ans[i]=tot;
64         hd[cp[i][0]]=nx[hd[cp[i][0]]];
65         hd[cp[i][1]]=nx[hd[cp[i][1]]];
66         for(int j=1;j>=0;j--)
67             if(!del[cp[i][j]])
68                 deg[cp[i][1-j]]--;
69         for(int j=1;j>=0;j--)
70             if(deg[cp[i][j]]<k)
71                 qq.push(cp[i][j]),split();
72     }
73     for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
74     return 0;
75 }

猜你喜欢

转载自www.cnblogs.com/eternhope/p/9842935.html