题意:
给出n个学生,m个社团,第二行给出n个pi表示学生的潜力,第三行给出n个ci表示学生一开始所在的社团,
然后输入q,接下来输入k行查询,每次输入一个ki表示第i天第ki个学生出离开所在的社团。然后每次查询询问这一天
所能获得的最大学生序列的最大的mex,(mex是序列中第一个出现的不存在的数字eg:{1,2,4,5}的mex是3)。
思路:
将每个学生视为社团与学校之间的边,可以先将所有的查询的学生标记,然后将所有未标记的学生连入图中,
然后查询第d次的mex,接着反向逐步插入学生(将学生连接到社团),然后统计第i次的mex。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 300300;
struct Node{
int v,nxt;
Node(){}
Node(int x,int y):v(x),nxt(y){}
}cur[maxn];
int head[maxn],ans[maxn],link[maxn],tot=0,p[maxn],c[maxn],vis[maxn],qy[maxn];
void addedge(int u,int v){
cur[tot] = Node(v,head[u]);
head[u] = tot++;
}
bool dfs(int u){
for(int i = head[u];~i;i=cur[i].nxt)
if(!vis[cur[i].v]){
vis[cur[i].v] = 1;
if(link[cur[i].v]==-1||dfs(link[cur[i].v])){
link[cur[i].v] = u;
return true;
}
}
return false;
}
int main(void)
{
int n,m,d,i,j;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++) scanf("%d",&p[i]);
for(i=1;i<=n;i++) scanf("%d",&c[i]),c[i]+=5000;
scanf("%d",&d);
memset(ans,0,sizeof(ans));
memset(vis,0,sizeof(vis));
fill(head,head+maxn,-1);
fill(link,link+maxn,-1);
for(i=1;i<=d;i++){
scanf("%d",&qy[i]);
vis[qy[i]] = 1;
}
for(i=1;i<=n;i++)
if(!vis[i]){
addedge(p[i],c[i]);
addedge(c[i],p[i]);
}
while(1){
memset(vis,0,sizeof(vis));
if(dfs(ans[d])) ans[d]++;
else break;
}
for(i=d-1;i>=1;i--){
addedge(p[qy[i+1]],c[qy[i+1]]);
addedge(c[qy[i+1]],p[qy[i+1]]);
ans[i] = ans[i+1];
while(1){
memset(vis,0,sizeof(vis));
if(dfs(ans[i])) ans[i]++;
else break;
}
}
for(i=1;i<=d;i++) printf("%d\n",ans[i]);
return 0;
}