二分图判定
题目大意:
给出一个简单无向图,每个点的度为3。判断能否将此图分解成若干爪的形式,使得每条边都只出现在唯一的爪中。(点可以多次出现在爪中)
解题思路:
可以将爪的中心点视为关键点,对于每个关键点只属于唯一的爪中,对于关键点周围的3个点均不可能成为其它爪的关键点(否则与题目不符),所以原图可以分解为关键点与非关键点,关键点与关键点之间没有边相连,同理非关键点之间也没有边,那么此题就可以转化为二分图的判定问题,使用二染色的模版即可。
#include<bits/stdc++.h>
using namespace std;
struct edge {
int u, v;
};
const int MAXN = 300;
struct T_T {
int n;
vector<edge> Edge;
vector<int> G[MAXN + 10];
void init(int n) {
Edge.clear();
for(int i = 1; i <= n; i++) G[i].clear();
}
void Addedge(int u, int v) {
Edge.push_back((edge){u, v});
G[u].push_back(Edge.size() - 1);
}
int color[MAXN + 10];
bool bipartite(int u) {
for(int i = 0; i < G[u].size(); i++) {
edge &e = Edge[G[u][i]];
if(color[e.u] == color[e.v]) return 0;
if(!color[e.v]) {
color[e.v] = 3 - color[e.u];
if(!bipartite(e.v)) return 0;
}
}
return 1;
}
void work() {
memset(color, 0, sizeof(color));
color[1] = 1;
if(bipartite(1)) puts("YES");
else puts("NO");
}
bool Read() {
int u, v;
if(scanf("%d", &n) != 1 || !n) return 0;
init(n);
while(scanf("%d%d", &u, &v) == 2 && (u || v)) {
Addedge(u, v);
Addedge(v, u);
}
return 1;
}
} sp;
int main() {
while(sp.Read())
sp.work();
return 0;
}