这个题目就是二分图最大匹配,然后输出字典序最小的那个编号,这个输出和[NOI2009]变换序列有点像,区别就是这个题水一些
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int M = 210;
bool g[M][M],vis[M],del[M],book[M];
int px[M],py[M];
int n;
bool Hun(int x) {
if(del[x]) return 0;
for(int i=0;i<n;i++) {
if(!g[x][i]||vis[i]||del[i]||!book[i]) continue;
vis[i] = 1;
if(py[i]==-1||Hun(py[i])) {
px[x]=i;
py[i]=x;
return 1;
}
}
return 0;
}
bool hun(int y) {
if(del[y]) return 0;
for(int i=0;i<n;i++) {
if(!g[y][i]||vis[i]||del[i]||book[i]) continue;
vis[i] = 1;
if(px[i]==-1||hun(px[i])) {
px[i]=y;
py[y]=i;
return 1;
}
}
return 0;
}
int main()
{
int t;
cin>>t;
while(t--) {
int m;
scanf("%d%d",&n,&m);
memset(g,0,sizeof(g));
memset(del,0,sizeof(del));
memset(px,-1,sizeof(px));
memset(py,-1,sizeof(py));
for(int i=0;i<n;i++) cin>>book[i];
for(int i=0;i<m;i++) {
int j,k;
cin>>j>>k;
if(book[j]!=book[k])
g[j][k]=g[k][j]=1;
}
int ans=0;
for(int i=0;i<n;i++)
if(book[i]==0) {
memset(vis,0,sizeof(vis));
ans+=Hun(i);
}
cout<<ans<<" ";
int x,y;
for(int i=0;i<n&&ans;i++) {
if(!book[i]) {
if(px[i]==-1 ) continue;
y=px[i];
del[i]=1;
px[i]=-1;
py[y]=-1;
memset(vis,0,sizeof(vis));
if(hun(y))
del[i] = 0;
cout<<i<<" ";
}
else
{
if(py[i] == -1) continue;
x = py[i];
del[i] = 1;
py[i] = -1;
px[x] = -1;
memset(vis,0,sizeof(vis));
if(Hun(x))
del[i] = 0;
cout<<i<<" ";
}
}
cout<<endl;
}
return 0;
}