[zyh_helen‘s Construction RoundT2]朝花题解
题目描述
给定一张 n 个点 m 条边简单无向图, 定义一次操作为:
-
选出 x≥3 个互不相同的节点;
-
把这些节点两两之间的边的状态取反(有边改为无边,无边改为有边);
-
该操作的代价为 x2。
让你在 20n+10m+100 的代价内将此图消成空图。
可以证明在给定数据范围一定有解。
输入格式
第一行两个数 n,m。
第 2 至 m+1 行每行两个数 u,v 表示图中的一条边。
输出格式
第一行一个数 c 表示你的操作总次数。
第 2 行至第 c+1 行,第 i+1 行先输出一个数 xi,后面 xi 个数表示第 i 次操作你选择的节点。
输入输出样例
输入 #1复制
6 4 1 2 3 4 1 3 2 4
输出 #1复制
2 3 1 2 3 3 2 3 4
输入 #2复制
6 1 1 2
输出 #2复制
6 6 1 2 3 4 5 6 4 3 4 5 6 3 1 2 3 3 1 2 4 3 1 2 5 3 1 2 6
说明/提示
样例解释
样例 1 中初始的边集为 {(1,2),(3,4),(1,3),(2,4)},第一次操作后变为 {(2,3),(3,4),(2,4)},第二次操作后变为空集。
数据范围
对于 30% 的数据,保证每个点的度数为偶数。
对于所有数据,n,m≤105,n≥6。
思路
先暴力枚举所有x>y,x>z式边,这样能令总边数减少,并使剩余边无公共节点。
然后,直接两条一起删除,若剩余,按题面做法即可。
代码见下
#include<bits/stdc++.h>
using namespace std;
long long n,m,u,vv,f[100005],lk=0,fo[300005],kl=0,op=0,lp[300005];
map<pair<int,int>,bool> mp;
vector<long long> v[100005];
vector<long long> v2[100005];
vector<long long> v3[300005];
struct{
long long u,v;
}uv[100005];
void abc(long long a1){
if(a1==0){
bool bo=1;
for(int i=1;i<=n;i++){
while(f[i]>=2){
bo=0;
long long x=0,y=0;
for(int j=0;j<v[i].size();j++){
if(mp[{i,v[i][j]}]!=0){
if(x==0){
x=j;
}
else{
y=j;
break;
}
}
}
if(mp[{v[i][x],v[i][y]}]==0){
v[v[i][x]].push_back(v[i][y]);
v[v[i][y]].push_back(v[i][x]);
mp[{v[i][x],v[i][y]}]=1;
mp[{v[i][y],v[i][x]}]=1;
mp[{i,v[i][y]}]=0;
mp[{v[i][x],i}]=0;
mp[{i,v[i][x]}]=0;
mp[{v[i][y],i}]=0;
f[i]-=2;
}
else{
mp[{v[i][x],v[i][y]}]=0;
mp[{v[i][y],v[i][x]}]=0;
mp[{i,v[i][y]}]=0;
mp[{v[i][x],i}]=0;
mp[{i,v[i][x]}]=0;
mp[{v[i][y],i}]=0;
f[i]-=2;
f[v[i][x]]-=2;
f[v[i][y]]-=2;
}
lk++;
fo[lk]=3;
v3[lk].push_back(i);
v3[lk].push_back(v[i][x]);
v3[lk].push_back(v[i][y]);
}
}
abc(bo);
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>u>>vv;
mp[{u,vv}]=1;
mp[{vv,u}]=1;
f[u]++;
f[vv]++;
v[u].push_back(vv);
v[vv].push_back(u);
v2[u].push_back(1);
v2[vv].push_back(1);
}
abc(0);
for(int i=1;i<=n;i++){
if(f[i]==1){
long long t2=0;
for(int j=0;j<v[i].size();j++){
if(mp[{v[i][j],i}]==1){
t2=v[i][j];
break;
}
}
mp[{t2,i}]=0;
mp[{i,t2}]=0;
f[i]--;
f[t2]--;
uv[++kl].u=i;
uv[kl].v=t2;
}
}
for(int i=2;i<=kl;i+=2){
lk++;
fo[lk]=3;
v3[lk].push_back(uv[i-1].u);
v3[lk].push_back(uv[i].u);
v3[lk].push_back(uv[i].v);
lk++;
fo[lk]=3;
v3[lk].push_back(uv[i-1].v);
v3[lk].push_back(uv[i].u);
v3[lk].push_back(uv[i].v);
lk++;
fo[lk]=4;
v3[lk].push_back(uv[i-1].u);
v3[lk].push_back(uv[i-1].v);
v3[lk].push_back(uv[i].u);
v3[lk].push_back(uv[i].v);
}
if(kl%2==1){
for(int i=1;i<=n;i++){
if(i!=uv[kl].u&&i!=uv[kl].v){
lp[++op]=i;
if(op==4){
break;
}
}
}
lk++;
fo[lk]=6;
v3[lk].push_back(lp[1]);
v3[lk].push_back(lp[2]);
v3[lk].push_back(lp[3]);
v3[lk].push_back(lp[4]);
v3[lk].push_back(uv[kl].u);
v3[lk].push_back(uv[kl].v);
lk++;
fo[lk]=4;
v3[lk].push_back(lp[1]);
v3[lk].push_back(lp[2]);
v3[lk].push_back(lp[3]);
v3[lk].push_back(lp[4]);
for(int i=1;i<=4;i++){
lk++;
fo[lk]=3;
v3[lk].push_back(lp[i]);
v3[lk].push_back(uv[kl].u);
v3[lk].push_back(uv[kl].v);
}
}
cout<<lk<<endl;
for(int i=1;i<=lk;i++){
cout<<fo[i]<<" ";
for(int j=0;j<v3[i].size();j++){
cout<<v3[i][j]<<" ";
}
cout<<endl;
}
return 0;
}

浙公网安备 33010602011771号