zoukankan      html  css  js  c++  java
  • 《牛客IOI周赛17提高组A》

    题意:对于题意可以分解为.

    有n个点,由n-1条白色的边连接,同时又有着m条边.

    因为这里说到了白色的边都不重复也不缠绕,显然是n-1条边构成树边.

    然后有m条非树边。然后问我们删去一条树边和一条非树边使树分为两部分。这条边完全断开.

    思路:

    我们可以从每条树边出发。

    对于每条树边。

    如果没有非树边覆盖到它.那么删去所有中任意的非树边都可以.即m种方案.
    如果有一条非树边覆盖到它,那么只有删去这条树边才可以.即1种方案.
    如果有两条及以上的非树边覆盖到它,那么删去非树边中的任意一条都不行,依旧会连通.所以此时方案为0.
     
    统计树边的覆盖情况采用树上差分的边差分.
     
    Code:
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 2e5+5;
    const int M = 1e6+5;
    const int Mod = 1e9+7;
    #define pi acos(-1)
    #define INF 1e8
    #define INM INT_MIN
    #define pb(a)  push_back(a)
    #define mk(a,b) make_pair(a,b)
    #define dbg(x) cout << "now this num is " << x << endl;
    #define met0(axx) memset(axx,0,sizeof(axx));
    #define metf(axx) memset(axx,-1,sizeof(axx));
    #define sd(ax) scanf("%d",&ax)
    #define sld(ax) scanf("%lld",&ax)
    #define sldd(ax,bx) scanf("%lld %lld",&ax,&bx)
    #define sdd(ax,bx) scanf("%d %d",&ax,&bx)
    #define sddd(ax,bx,cx) scanf("%d %d %d",&ax,&bx,&cx)
    #define sfd(ax) scanf("%lf",&ax)
    #define sfdd(ax,bx) scanf("%lf %lf",&ax,&bx)
    #define pr(a) printf("%d\n",a)
    #define plr(a) printf("%lld\n",a)
    /*
    对于一条树边.
    如果没有非树边覆盖到它.那么所有的非树边都可以.即m.
    如果有一条非树边覆盖到它,那么删去这条树边.即1.
    如果有两条及以上的非树边覆盖到它,那么删去非树边中的任意一条都不行,依旧会连通.所以此时方案为0
    */
    vector<int> G[N];
    int n,m,dep[N],f[N][25],lg[25],c[N];//i到父节点的边被多少条非树边覆盖
    LL ans = 0;
    void init()
    {
        lg[0] = 1;for(int i=1;i<25;++i) lg[i] = lg[i-1]<<1;
    }
    void dfs(int u,int fa)
    {
        dep[u] = dep[fa]+1;
        f[u][0] = fa;
        for(int i=1;i<25;++i) f[u][i] = f[f[u][i-1]][i-1];
        for(auto v:G[u]) if(v != fa) dfs(v,u);
    }
    int Lca(int x,int y)
    {
        if(dep[x] < dep[y]) swap(x,y);
        int dix = dep[x]-dep[y];
        for(int i=24;i>=0;--i)
        {
            if(lg[i] <= dix) dix -= lg[i],x = f[x][i];
        }
        if(x == y) return x;
        for(int i=24;i>=0;--i)
        {
            if(lg[i] <= dep[x] && f[x][i] != f[y][i]) x = f[x][i],y = f[y][i];
        }
        return f[x][0];
    }
    void dfs1(int u,int fa)
    {
        for(auto v:G[u])
        {
            if(v == fa) continue;
            dfs1(v,u);
            c[u] += c[v];
            if(c[v] == 0) ans += m;
            else if(c[v] == 1) ans++;
            //else都不能.
        }
    }
    void slove()
    {
        init();
        sdd(n,m);
        for(int i=1;i<n;++i)
        {
            int u,v;sdd(u,v);
            G[u].pb(v),G[v].pb(u);
        }
        dfs(1,0);
        for(int i=1;i<=m;++i)
        {
            int u,v;sdd(u,v);
            c[u]++,c[v]++,c[Lca(u,v)]-=2;
        }
        dfs1(1,0);
        plr(ans);
    }  
    int main()
    {
        slove();
        system("pause");
        return 0;
    }
    View Code
  • 相关阅读:
    青岛理工大学邀请赛总结
    HDU 1232 并查集/dfs
    HDU 1556
    HDU 5228
    POJ1011
    线段树(数组实现)
    NOIP2008 普及组T1 ISBN号码 解题报告-S.B.S.
    NOIP2008 普及组T4 立体图 解题报告-S.B.S.(施工未完成)
    noip2008普及组4题题解-rLq
    noip2008普及组3题题解-rLq
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/13061911.html
Copyright © 2011-2022 走看看