一个图论题:给定一个 n 个点、m 条边的无向简单图(无自环、重边)。定义下面的过程为一次删点:
找到任意一对度数相同的点 u 和 v,删去点 u 及其连出去的所有边。
任务是不断删点直到图中只剩一个点,输出任意删点过程都判对。n <= 10^5,m<=2*10^5,所以要保证时间复杂度正确,O(nlogn) 量级差不多。然后尽量用 C++ STL 吧(讲清思路也行)。
不知道 CSDN 还有没有真人回答问题,还是发一下吧/fn
一个图论题:给定一个 n 个点、m 条边的无向简单图(无自环、重边)。定义下面的过程为一次删点:
找到任意一对度数相同的点 u 和 v,删去点 u 及其连出去的所有边。
任务是不断删点直到图中只剩一个点,输出任意删点过程都判对。n <= 10^5,m<=2*10^5,所以要保证时间复杂度正确,O(nlogn) 量级差不多。然后尽量用 C++ STL 吧(讲清思路也行)。
不知道 CSDN 还有没有真人回答问题,还是发一下吧/fn
🕒上午好,题主!目前:🟢[在线]
📢参考GPT-4o mini 模型、由清水白石008整理提供!
📣今日金句:“生活就像骑自行车。要保持平衡,就得不断前进。” — 阿尔伯特·爱因斯坦
这是一道图论题,我们可以使用数据结构map
和vector
等C++ STL来解决。
首先,我们需要统计每个点的度数,可以使用一个map
来存储点的度数信息。具体来说,我们可以将点的编号id
作为map
的键,度数作为map
的值。
接下来,我们需要找到度数相同的两个点,可以使用两个vector
来存储度数为偶数和奇数的点的编号。每次我们从偶数vector
中取出一个点u
,从奇数vector
中取出一个点v
,如果u
和v
的度数相同,则删除点u
及其连出去的所有边。
具体来说,我们可以将点u
的所有相邻点都从map
中删除,并将它们的度数减一。如果某个相邻点的度数变为零,则将其从奇数vector
中删除。同时,我们需要将点u
从map
中删除,并将它的度数从偶数vector
中删除。
最后,我们重复上述过程,直到图中只剩一个点为止。
以下是C++代码实现:
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
const int MAXN = 1e5 + 5;
int n, m;
map<int, int> mp;
vector<int> even, odd;
int main() {
cin >> n >> m;
for (int i = 1, u, v; i <= m; i++) {
cin >> u >> v;
mp[u]++, mp[v]++;
even.push_back(u);
odd.push_back(v);
}
while (even.size() > 1) {
int u = even.back(); even.pop_back();
int v = odd.back(); odd.pop_back();
if (mp[u] == mp[v]) {
for (auto it = mp.begin(); it != mp.end(); ) {
if (it->second == 0) mp.erase(it++);
else if (it->second-- == 1) odd.erase(remove(odd.begin(), odd.end(), it->first), odd.end());
else it++;
}
mp.erase(u);
}
}
if (even.size() == 1) cout << even[0] << endl;
else cout << -1 << endl;
return 0;
}
时间复杂度分析:
空间复杂度分析:
map
来存储点的度数信息,空间复杂度为O(n)。vector
来存储度数为偶数和奇数的点的编号,空间复杂度为O(m)。首先,我们需要统计每个点的度数,可以使用一个map
来存储点的度数信息。具体来说,我们可以将点的编号id
作为map
的键,度数作为map
的值。
接下来,我们需要找到度数相同的两个点,可以使用两个vector
来存储度数为偶数和奇数的点的编号。每次我们从偶数vector
中取出一个点u
,从奇数vector
中取出一个点v
,如果u
和v
的度数相同,则删除点u
及其连出去的所有边。
具体来说,我们可以将点u
的所有相邻点都从map
中删除,并将它们的度数减一。如果某个相邻点的度数变为零,则将其从奇数vector
中删除。同时,我们需要将点u
从map
中删除,并将它的度数从偶数vector
中删除。
为了避免重复删除相同的边,我们可以使用一个set
来存储已经删除的边。每次删除一条边时,我们可以将其加入set
中,如果下一次删除相同的边,则可以直接跳过。
最后,我们重复上述过程,直到图中只剩一个点为止。
以下是C++代码实现:
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
const int MAXN = 1e5 + 5;
int n, m;
map<int, int> mp;
vector<int> even, odd;
set<pair<int, int>> st;
int main() {
cin >> n >> m;
for (int i = 1, u, v; i <= m; i++) {
cin >> u >> v;
mp[u]++, mp[v]++;
even.push_back(u);
odd.push_back(v);
}
while (even.size() > 1) {
int u = even.back(); even.pop_back();
int v = odd.back(); odd.pop_back();
if (mp[u] == mp[v]) {
for (auto it = mp.begin(); it != mp.end(); ) {
if (it->second == 0) mp.erase(it++);
else if (it->second-- == 1) {
if (st.find({min(u, v), max(u, v)}) == st.end()) {
odd.erase(remove(odd.begin(), odd.end(), it->first), odd.end());
st.insert({min(u, v), max(u, v)});
}
} else it++;
}
mp.erase(u);
}
}
if (even.size() == 1) cout << even[0] << endl;
else cout << -1 << endl;
return 0;
}
时间复杂度分析:
空间复杂度分析:
map
来存储点的度数信息,空间复杂度为O(n)。vector
来存储度数为偶数和奇数