题目:https://www.luogu.org/problemnew/show/P1330
此题我最初没有思路,暴搜而爆0;
然后才明白关键在于把所有点分成两类,因为可以发现点之间的关系是存在两两对立的;
这样一张图的情况就是固定的,确定一个点就能够确定其他所有点,因为一条边的两个点必然属于不同的类别,可以通过遍历边来进行深搜染色;
最后取各连通块中较少的那一类点,相加即为结果;
而若在染色中出现矛盾,则一定为“Impossible”。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int n,m,a,b,cnt[10005],ct,col[10005],s[5],ans;
struct N{
int to;int next;
}edge[200005];//!
void add(int x,int y)
{
ct++;
edge[ct].to=y;
edge[ct].next=cnt[x];
cnt[x]=ct;
}
void dfs(int x)
{
for(int i=cnt[x];i;i=edge[i].next)
{
int v=edge[i].to;
if(col[v]==col[x])
{
printf("Impossible");
exit(0);
}
if(!col[v])
{
col[v]=3-col[x];
s[col[v]]++;
dfs(v);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
add(a,b);add(b,a);
}
for(int i=1;i<=ct;i++)
{
int v=edge[i].to;
s[1]=0;s[2]=0;
if(!col[v])
{
col[v]=1;
s[col[v]]++;
dfs(v);
ans+=min(s[1],s[2]);
}
}
printf("%d",ans);
return 0;
}