-
初刷时间:2023.9.22
-
解题思路:
- 首先统计所有节点的度,并用一个有序集合记录已经存在的边的信息
- 统计度数为奇数的节点,并将这些节点存在points中
- 如果度数为奇数的节点个数大于4,或其个数为奇数,直接返回false
- 此时节点个数只可能是2个或4个,分情况进行讨论
-
如果是2个,则可能存在两种连接情况
- 两个点直接相连,直接检查这条边在不在集合中,如果不在,返回true
- 两个点借助一个中间点进行连接,分别检查中间点与两个点的边在不在集合中,如果均不在,返回true
-
如果是4个,则将这4个点两两组合共有3种组合方法,分别检查各边在不在集合中,只有两条边均不在时返回true
-
其余情况都返回false
-
-
解题代码:
class Solution {
public:
bool isPossible(int n, vector<vector<int>>& edges) {
vector<int> deg(n, 0);
set<pair<int, int>> s;
for(auto &edge : edges)
{
int x = edge[0] - 1;
int y = edge[1] - 1;
deg[x] += 1;
deg[y] += 1;
s.insert({min(x, y), max(x, y)});
}
int cnt = 0;
vector<int> points;
for(int i = 0; i < n; i++)
{
if(deg[i] & 1)
{
cnt += 1;
points.emplace_back(i);
}
}
if(cnt > 4 || (cnt & 1))//奇数点个数大于 或 奇数点个数为奇数
return false;
if(cnt == 0)
return true;
//接下来就要判断能不能加两条边解决问题
//此时有两个点, 或有四个点
//四个点的话就是两两连一条边
if(cnt == 4)
{
int p1 = points[0];
int p2 = points[1];
int p3 = points[2];
int p4 = points[3];
if(!s.count({p1, p2}) && !s.count({p3, p4}))
return true;
if(!s.count({p1, p3}) && !s.count({p2, p4}))
return true;
if(!s.count({p1, p4}) && !s.count({p2, p3}))
return true;
}
//两个点的话有两种可能,两点之间直接连一条边,或找一个中间节点,两点都向中间节点连一条边
if(cnt == 2)
{
int p1 = points[0];
int p2 = points[1];
if(!s.count({p1, p2}))
return true;
for(int i = 0; i < n; i++)
{
if(i == p1 || i == p2)
continue;
if(!s.count({min(i, p1), max(i, p1)}) && !s.count({min(i, p2), max(i, p2)}))
return true;
}
}
return false;
}
};