杭电多校6 1002
题意:
给定一个无重边无自环但可能非连通的图,
n
n
n个点,
m
m
m条边。定义混沌点为删除该点以及该点的所有连边后,剩下的所有连通块均为菊花图。求所有的混沌点。
题解:
主要的
c
h
e
c
k
check
check是判别一个连通块是否为菊花图,存在两种情况, 一种是不删点的情况下已然是菊花图,另一种是必须删点才能形成菊花图。判别菊花图可以通过点的度数来判断,当一个连通块的只有一个或零个点度数不为
1
1
1,且它连向的所有点度数均为
1
1
1,则其为菊花图,那么我们就可以暴力地去枚举每个连通块,如果最后非菊花图的连通块数量大于一,那么显然输出
−
1
-1
−1,否则,就找唯一的菊花图的某一个四元组,满足其形成的子图为非菊花图,然后枚举删每一个点,计算删完之后剩余的子图是否为菊花图即可。
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define debug(p) for (auto i : p)cerr << i << " "; cerr << endl;
#define debugs(p) for (auto i : p)cerr << i.first << " " << i.second << endl;
typedef pair<int, int> pll;
string yes = "YES";
string no = "NO";
constexpr int N = 1e4 + 7;
vector<int>edge[N];
int n, m;
int deg[N];
bool vis[N];
vector<int>pt;
void dfs(int u, int f)
{
vis[u] = 1;
pt.push_back(u);
for (auto v : edge[u])
{
if(v == f || vis[v])continue;
dfs(v, u);
}
}
void init()
{
for (int i = 0; i <= n; i++)
{
vis[i] = 0;
deg[i] = 0;
edge[i].clear();
}
}
void solve()
{
cin >> n >> m;
for (int i = 0; i < m; i++)
{
int u, v;
cin >> u >> v;
deg[u]++, deg[v]++;
edge[u].push_back(v);
edge[v].push_back(u);
}
vector<int>tt;
int cnt = 0;
for (int i = 1; i <= n; i++)
{
// cerr << "1" << endl;
pt.clear();
if(!vis[i])dfs(i, -1);
int cnt1 = 0, cnt2 = 0;
// cerr << "2" << endl;
bool f = 1;
for (int j = 0; j < pt.size(); j++)
{
int u = pt[j];
if(deg[u] != 1)
{
for (auto v : edge[u])
{
if(deg[v] != 1)
{
f = 0;
break;
}
}
}
if(!f)break;
}
if(!f)
{
cnt++;
for (int j = 0; j < pt.size(); j++)tt.push_back(pt[j]);
}
}
if(cnt > 1)
{
cout << -1 << endl;
init();
return;
}
else if(cnt == 0)
{
for (int i = 1; i <= n; i++)cout << i << " \n"[i == n];
init();
return;
}
vector<int>del;
// debug(tt);
for (int i = 0; i < tt.size(); i++)
{
int u = tt[i];
if(deg[u] == 1)continue;
int v = -1;
for (auto temp : edge[u])
{
if(deg[v] == 1)continue;
v = temp;
break;
}
if(v == -1)continue;
int a, b;
for (auto temp : edge[u])
{
if(temp == v)continue;
a = temp;
break;
}
for (auto temp : edge[v])
{
if(temp == u)continue;
b = temp;
break;
}
del.push_back(u);
del.push_back(v);
del.push_back(a);
if(a != b)del.push_back(b);
}
sort(del.begin(), del.end());
del.erase(unique(del.begin(), del.end()), del.end());
vector<int>ans;
// debug(del);
for (int i = 0; i < del.size(); i++)
{
int u = del[i];
for (auto v : edge[u])
{
deg[v]--;
}
bool f = 1;
for (int j = 0; j < tt.size(); j++)
{
int uu = tt[j];
if(uu == u)continue;
if(deg[uu] != 1)
{
for (auto v : edge[uu])
{
if(v == u)continue;
if(deg[v] != 1)
{
f = 0;
break;
}
}
}
if(!f)break;
}
if(f)ans.push_back(u);
for (auto v : edge[u])
{
deg[v]++;
}
}
sort(ans.begin(), ans.end());
if((int)ans.size() == 0)cout << -1 << endl;
else
{
for (int i = 0; i < ans.size(); i++)
{
cout << ans[i] << " \n"[i == ans.size() - 1];
}
}
init();
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int T = 1;
cin >> T;
while(T--)
{
solve();
}
}