题目地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1925
思路:
1.求一点集,使得其为图的最小覆盖集和最大独立集。
2.首先,若该图不为二分图,则必无解:若不为二分图,则存在奇数长度回路,设该回路上点数为2*k+1。则由定义,至多k个点在最大独立集中,至少k+1个点在最小覆盖集中,矛盾。所以必不存在奇数长度回路。
2.二分图条件下,X部与Y部点数必相同:由二分图性质得最大匹配数=最小覆盖集大小,最大独立集大小=n-最大匹配数。由于最大匹配数不大于min{|X|,|Y|},所以最小覆盖集不超过min{|X|,|Y|}。则最大独立集不小于max{|X|,|Y|},则若最大独立集大小等于最小覆盖集大小则必须|X|等于|Y|。
3.由于最大独立集大小等于最小覆盖集大小,即最大匹配数=n-最大匹配数,则最大匹配数等于n/2存在解(由2,n为奇数必无解)。
4.综上,点集即为X部或Y部。
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define S 0
#define T n+1
#define debug
using namespace std;
const int maxn = 10000+10;
const int INF = 0x3f3f3f3f;
struct Edge
{
int to,nt;
};
int tot,n,m;
vector<int> ans[2];
Edge edge[maxn*200];
int col[maxn],disy[maxn];
int head[maxn],matx[maxn];
int maty[maxn],disx[maxn];
void addEdge(int u,int v)
{
edge[tot].to=v,edge[tot].nt=head[u],head[u]=tot++;
}
void init()
{
tot=0;
memset(col,-1,sizeof(col));
memset(head,-1,sizeof(head));
ans[0].clear(),ans[1].clear();
}
int check(int s)
{
queue<int> q;
q.push(s),col[s]=0;
while(!q.empty())
{
int now=q.front();
q.pop();
ans[col[now]].push_back(now);
for(int i=head[now]; ~i; i=edge[i].nt)
{
int nt=edge[i].to;
if(col[nt]==-1)
{
col[nt]=col[now]^1;
q.push(nt);
}
else if(col[nt]==col[now])
{
return 0;
}
}
}
return 1;
}
bool bfs()
{
queue<int> q;
memset(disx,-1,sizeof(disx));
memset(disy,-1,sizeof(disy));
for(int i=1;i<=n;i++)
{
if(matx[i]==-1)
{
q.push(i);
disx[i]=0;
}
}
bool flg=0;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];~i;i=edge[i].nt)
{
int nt=edge[i].to;
if(disy[nt]==-1)
{
disy[nt]=disx[u]+1;
if(maty[nt]==-1) flg=1;
else
{
disx[maty[nt]]=disy[nt]+1;
q.push(maty[nt]);
}
}
}
}
return flg;
}
bool dfs(int u)
{
for(int i=head[u];~i;i=edge[i].nt)
{
int nt=edge[i].to;
if(disy[nt]==disx[u]+1)
{
disy[nt]=0;
if(maty[nt]==-1||dfs(maty[nt]))
{
maty[nt]=u;
matx[u]=nt;
return 1;
}
}
}
return 0;
}
int maxMatch()
{
int ret=0;
memset(matx,-1,sizeof(matx));
memset(maty,-1,sizeof(maty));
while(bfs())
{
for(int i=1;i<=n;i++)
{
if(matx[i]==-1&&dfs(i)) ret++;
}
}
return ret;
}
int main()
{
#ifdef debu
freopen("in.txt","r",stdin);
#endif // debug
int t,cas=0;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
for(int i=1; i<=m; i++)
{
int x,y;
scanf("%d%d",&x,&y);
addEdge(x,y),addEdge(y,x);
}
int flag=1;
if(n&1) flag=0;
for(int i=1; i<=n; i++)
{
if(col[i]==-1&&!check(i))
{
flag=0;
break;
}
}
if(ans[0].size()*2!=n) flag=0;
if(maxMatch()!=n) flag=0;
printf("Case #%d: ",++cas);
if(!flag) printf("Impossible\n");
else
{
printf("%d\n",ans[0].size());
sort(ans[0].begin(),ans[0].end());
for(int i=0; i<ans[0].size(); i++)
{
if(i==0) printf("%d",ans[0][i]);
else printf(" %d",ans[0][i]);
}
printf("\n");
}
}
return 0;
}