「杂题乱刷2」CF1186F
题目链接
CF1186F Vus the Cossack and a Graph
解题思路
大家好,我不会欧拉路径,所以讲一下其他做法。
首先我们要有惊人的注意力。
发现若 \(n \ge m\) 时,取所有边即可。
否则首先按照初始度数从小到大开始连边,尽量连成有贡献的边即可,因为这样若每次都达成贡献,则一定最优。
注意到这样过不了,我们将边随机打乱后做即可,这样次数由于比较宽松,可以证明最终边数一定在规定次数内。
参考代码
ll n,m;
ll x,y;
pii D[1000010];
ll need[1000010];
map<ll,map<ll,ll>>mp;
vector<ll>G[1000010];
ll now[1000010];
pii E[1000010];
ll id[1000010];
ll find(ll x)
{
if(id[x]==x)
return x;
return id[x]=find(id[x]);
}
vector<pii>ans;
void _clear(){}
void solve()
{
_clear();
cin>>n>>m;
if((n+m+1)/2>=m)
{
cout<<m<<endl;
forl(i,1,m)
cout<<rd()<<' '<<rd()<<endl;
return ;
}
forl(i,1,n)
id[i]=i;
forl(i,1,m)
cin>>x>>y,
D[x].x++,D[y].x++,
E[i]={x,y},
G[x].pb(y),G[y].pb(x);
forl(i,1,n)
random_shuffle(G[i].begin(),G[i].end());
forl(i,1,n)
need[i]=(D[i].x+1)/2,
D[i].y=i;
sort(D+1,D+1+n);
forl(i,1,n)
{
for(auto j:G[D[i].y])
if(now[D[i].y]<need[D[i].y] && now[j]<need[j] && !mp[D[i].y][j])
mp[D[i].y][j]=mp[j][D[i].y]=1,
now[D[i].y]++,
now[j]++,
ans.pb({D[i].y,j});
for(auto j:G[D[i].y])
if(now[D[i].y]<need[D[i].y] && !mp[D[i].y][j])
mp[D[i].y][j]=mp[j][D[i].y]=1,
now[D[i].y]++,
now[j]++,
ans.pb({D[i].y,j});
}
for(auto i:ans)
id[find(i.x)]=find(i.y);
forl(i,1,m)
if(find(E[i].x)!=find(E[i].y))
id[find(E[i].x)]=find(E[i].y),
ans.pb({E[i].x,E[i].y});
cout<<ans.size()<<endl;
for(auto i:ans)
cout<<i.x<<' '<<i.y<<endl;
}

浙公网安备 33010602011771号