「杂题乱刷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;
}
posted @ 2025-04-09 15:20  wangmarui  阅读(15)  评论(0)    收藏  举报