• 352. 闇の連鎖


    352. 闇の連鎖

    这道题挺妙的,说到底还是自己的思维不行啊....

    首先我们在拿到题目时,要深刻的对模型之类的东西进行运用...

    一个树,加上m个非树边,第一次割掉树边,第二次割掉非树边,使得整个图不连通.问有多少个方案.

    我们考虑一个树,加上一个边(x,y)。那x,y之间的路径加上这条边就形成一个环.

    对于(x,y)之间的树边而言,如果我们割掉任何一条边,整个图仍是联通的.所以我们下一步必须割掉链接x,y的非树边才能使得这个图不连通

    所以我们将x到y的路径上的边都加1.意思是割掉这些边后必须割掉一条边才能使得整个图不连通.

    我们对所有的非树边都这样做,对于一条边,他会有一个数值x,意思是割掉这条边后,必须割掉x条边才能使得整个图不连通.

    当然可能存在值为0的边,意思是割掉他后图就不连通..

    这样之后我们要求方案树就容易多了...

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=100010;
    int n,m,link[N],c[N],tot,f[N][25],deep[N],ans;
    struct edge{int y,next;}a[N<<1];
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
    inline void add(int x,int y)
    {
        a[++tot].y=y;a[tot].next=link[x];link[x]=tot;
        a[++tot].y=x;a[tot].next=link[y];link[y]=tot;
    }
    inline void bfs()
    {
        queue<int>q;q.push(1);
        deep[1]=1;
        while(!q.empty())
        {
            int x=q.front();q.pop();
            for(int i=link[x];i;i=a[i].next)
            {
                int y=a[i].y;
                if(deep[y]) continue;
                deep[y]=deep[x]+1;
                q.push(y);
                f[y][0]=x;
                for(int j=1;j<=20;++j) f[y][j]=f[f[y][j-1]][j-1];
            } 
        }
    }
    inline int lca(int a,int b)
    {
        if(deep[a]>deep[b]) swap(a,b);
        for(int i=20;i>=0;--i)
            if(deep[f[b][i]]>=deep[a]) b=f[b][i];
        if(a==b) return a;
        for(int i=20;i>=0;--i)
            if(f[b][i]!=f[a][i]) a=f[a][i],b=f[b][i];
        return f[a][0];    
    }
    inline void dfs(int x)
    {
        for(int i=link[x];i;i=a[i].next)
        {
            int y=a[i].y;
            if(y==f[x][0]) continue;
            dfs(y);
            c[x]+=c[y];
        }
        if(c[x]==1) ans++;
        else if(c[x]==0) ans+=m;
    }
    int main()
    {
        //freopen("1.in","r",stdin);
        n=read();m=read();
        for(int i=1;i<n;++i)
        {
            int x=read(),y=read();
            add(x,y);
        }
        bfs();
        for(int i=1;i<=m;++i)
        {
            int x=read(),y=read();
            int o=lca(x,y);
            c[x]++;c[y]++;c[o]-=2;
        }
        dfs(1);
        printf("%d",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    c++<ctime>中常用函数
    头文件<cmath>中常用函数
    c++动态数组的使用
    迭代器与指针
    引用和指针做形参时的区别
    c++使用cin、cout与c中使用scanf、printf进行输入输出的效率问题
    c++指定输出小数的精度
    Linux命令学习(1)
    Nginx 配置文件nginx.conf中文详解
    Walle实现自动发布
  • 原文地址:https://www.cnblogs.com/gcfer/p/12464608.html
Copyright © 2020-2023  润新知