从题目中可以看出,能够完全封锁的图一定是一个二分图
只要占领一个点集(U或V)就可以封锁全部的道路
最少的河蟹数量就是较少的那个点集
上图中最少需要4只河蟹(V集合)
用dfs染色法判断是否为二分图,再用两个变量来记录不同颜色的点数
二分图中,若染源点为1,则源点的子节点染色为2,源点的,子节点的子节点染色为1
如果遇到了子节点和父节点颜色相同的情况,则无法构成二分图
因为如果颜色相同,则两个点在一个点集中。而二分图的一个点集内的节点是没有边相连的,所以直接输出Impossible
由于不只有一个图,答案是每个图的最小点集之和。
PS:一开始,t1 = 1, t2 = 0。因为源点是在dfs之前提前染色,所以dfs之前,有一个点集已经有了一个点。
#include <cstdio>
#include <algorithm>
#include <cstring>
const int maxn = 10010;
int n,m,last[maxn],tot,dye[maxn],ans,t1,t2;
inline void read(int &x) { //快速读入
x = 0;
char c = getchar();
while(c<'0'||c>'9') c = getchar();
while(c>='0'&& c<='9') x = x*10 + c-'0', c = getchar();
return;
}
struct Edge{
int u,v,to;
Edge(){}
Edge(int u, int v, int to) : u(u), v(v), to(to) {}
}e[2*10*maxn+10];
void addedge(int u,int v) {
e[++tot] = Edge(u, v, last[u]);
last[u] = tot;
}
void dfs(int u) {
for(int i=last[u]; i; i=e[i].to) {
int v = e[i].v;
if(dye[v] == dye[u]) {
printf("Impossible");
exit(0); //无条件退出程序
}
if(!dye[v]) {
dye[v] = dye[u] == 1 ? 2 : 1;
if(dye[v] == 1) t1++;
else t2++;
dfs(v);
}
}
}
int main() {
read(n), read(m);
for(int i=1; i<=m; i++) {
int u, v;
read(u);
read(v);
addedge(u,v);
addedge(v,u);
}
for(int i=1; i<=n; i++) {
t1 = 1;
t2 = 0;
if(!dye[i]) dye[i] = 1, dfs(i);
ans += std::min(t1, t2);
}
printf("%d", ans);
return 0;
}