You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
2.4 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10; //题目中说结点数最大10^4=1e4
const int M = 1e5 * 2 + 10; //边数上限因为是无向图所以记录两次就是1e5*2
/*
Impossible
min
minmin
*/
int color[N]; //0:未上色1黑色2白色
int n, m, ans;
//广度优先搜索的队列
queue<int> q;
//链式前向星
struct Edge {
int to, next;
} edge[M];
int idx, head[N];
void add(int u, int v) {
edge[++idx].to = v;
edge[idx].next = head[u];
head[u] = idx;
}
//广度优先搜索
int bfs(int a) {
int ans1 = 1, ans2 = 0;
color[a] = 1;//假设用颜色1着了色
q.push(a);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
//目标点未着色
if (color[v] == 0) {
//来源点是黑的,那么目标点是白的
if (color[u] == 1) color[v] = 2, ans2++;
//来源点是白的,那么目标点是黑的
else if (color[u] == 2) color[v] = 1, ans1++;
q.push(v);
} else
//如果已着色,那么需要判断和现在的要求是不是有冲突:
if (color[v] == color[u]) {//相临的存在冲突
printf("Impossible");
exit(0);
}
}
}
//哪个小就用哪个
return min(ans1, ans2);
}
int main() {
//n个结点m条边
cin >> n >> m;
//m条边
for (int i = 1; i <= m; ++i) {
int x, y;
cin >> x >> y;
add(x, y), add(y, x); //无向图双向建边,题目中明显说是无向图!
}
//注意图可能不连通。因此对于每个二分图都要进行取min操作
//而不是对整个图染色后取min。
//这里有一个小技巧,就是遍历每个结点,如果此结点没有上过色,就表示是一个独立的图,需要单独计算
for (int i = 1; i <= n; ++i)
if (!color[i]) ans += bfs(i);
//输出
printf("%d", ans);
return 0;
}