zoukankan      html  css  js  c++  java
  • CCPC-Wannafly Winter Camp Day4 Div1

    题目链接:https://zhixincode.com/contest/18/problem/C?problem_id=261

    样例输入 1

    4 2
    1 2
    3 4

    样例输出 1

    Yes

    样例输入 2

    4 3
    1 2
    2 3
    3 4

    样例输出 2

    No

    题解:

    判断一个边集是否为最小边覆盖,用最笨的方法,暴力枚举边集内所有边进行删除,看删除后是否依然覆盖所有点,这个可以用线段树优化成 $O(log n)$ 的时间复杂度,就可以过了。这是一个比较直观的做法。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef pair<int,int> pii;
    #define x(p) (p.first)
    #define y(p) (p.second)
    const int maxn=2e5+10;
    const int maxm=3e5+10;
    
    int n,m;
    int d[maxn];
    pii e[maxm];
    
    #define ls (rt<<1)
    #define rs (rt<<1|1)
    struct Node{
        int l,r;
        int val;
        bool ok;
    }o[maxn<<2];
    void pushup(int rt)
    {
        o[rt].val=o[ls].val+o[rs].val;
        o[rt].ok=o[ls].ok&o[rs].ok;
    }
    void build(int rt,int l,int r)
    {
        o[rt].l=l, o[rt].r=r;
        if(l==r)
        {
            o[rt].val=d[l];
            o[rt].ok=(o[rt].val>0);
            return;
        }
        int mid=(l+r)>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
        pushup(rt);
    }
    void update(int rt,int pos,int val)
    {
        if(o[rt].l==o[rt].r)
        {
            o[rt].val+=val;
            o[rt].ok=(o[rt].val>0);
            return;
        }
        int mid=(o[rt].l+o[rt].r)>>1;
        if(pos<=mid) update(ls,pos,val);
        if(pos>mid) update(rs,pos,val);
        pushup(rt);
    }
    
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0), cout.tie(0);
    
        cin>>n>>m;
        for(int i=1;i<=m;i++)
        {
            cin>>x(e[i])>>y(e[i]);
            d[x(e[i])]++, d[y(e[i])]++;
        }
    
        build(1,1,n);
        bool ans=o[1].ok;
        if(!ans) cout<<"No
    ";
        else
        {
            for(int i=1;i<=m;i++)
            {
                update(1,x(e[i]),-1), update(1,y(e[i]),-1);
                if(o[1].ok) {ans=0; break;}
                update(1,x(e[i]),1), update(1,y(e[i]),1);
            }
            cout<<(ans?"Yes":"No")<<'
    ';
        }
    }

    另一个题解:

    然后仔细想一下上面的思路,就会发现有点蠢。因为删掉一条边,若依然能覆盖所有点,那么必然这条边的两个端度数大于等于 $2$,因此直接判一下每条边的端点度数就好了。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef pair<int,int> pii;
    #define x(p) (p.first)
    #define y(p) (p.second)
    const int maxn=2e5+10;
    const int maxm=3e5+10;
    
    int n,m;
    int d[maxn];
    pii e[maxm];
    
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0), cout.tie(0);
    
        cin>>n>>m;
        for(int i=1;i<=m;i++)
        {
            cin>>x(e[i])>>y(e[i]);
            d[x(e[i])]++, d[y(e[i])]++;
        }
    
        bool ok=1;
        for(int i=1;i<=n;i++) ok&=(d[i]>0);
        if(!ok) {cout<<"No
    "; return 0;}
        for(int i=1;i<=m;i++) if(d[x(e[i])]>1 && d[y(e[i])]>1) {ok=0; break;}
        if(ok) cout<<"Yes
    ";
        else cout<<"No
    ";
    }

    PS.线段树什么的,只能当做练手了qwq

  • 相关阅读:
    教你怎么叠T恤
    最动人的情歌《The Power of Love》by Celine.Dion
    使代码简洁的 5 条忠告
    Timeout MessageBox
    内联函数
    局部对象
    const用法(转)
    心情
    内联函数
    局部对象
  • 原文地址:https://www.cnblogs.com/dilthey/p/10383836.html
Copyright © 2011-2022 走看看