• 删边(cip)


     删边(cip)

    给出一个没有重边和自环的无向图,现在要求删除其中两条边,使得图仍然保持连通。

    你的任务是计算有多少组不合法的选边方案。注意方案是无序二元组。


    Sol

    神题,无从下手啊。

    考虑点dfs建出dfs树,边分为两种--树边,非树边。

    那么割断两条非树边显然不行。

    考虑割一条树边a和一条非树边b,当b为a子树内唯一返祖边或a子树无返祖边时不行。

    考虑两条树边ab,我们把一条返祖边打在它覆盖的所有树边上,如果这两条非树边被覆盖的集合相同,那么他们中间的那一段就会断开,就可以。

    于是可以把每条返祖边给个hash值,开始处加,结束处减,统计每条边的覆盖集合,在排序统计下就行。

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define maxn 300005
    #define rand() ((rand()<<15)|rand())
    #define ll unsigned long long
    using namespace std;
    int n,m,head[maxn],tot,flag[maxn],t;
    int sum[maxn],sz[maxn],a[maxn],deep[maxn];
    struct node{
        int v,nex;int h;
    }e[maxn*2];
    ll ans,ha[maxn];
    void add(int t1,int t2){
        e[++tot].v=t2;e[tot].nex=head[t1];head[t1]=tot;
    }
    void dfs(int k,int fa){
        flag[k]=1; deep[k]=deep[fa]+1;
        for(int i=head[k];i;i=e[i].nex){
            if(flag[e[i].v]){
                if(e[i].v!=fa&&deep[e[i].v]<deep[k]){
                    ha[e[i].v]-=e[i].h;
                    ha[k]+=e[i].h;
                    sz[k]++;sz[e[i].v]--;
                }
                continue;
            }
            dfs(e[i].v,k);
        }
    }
    void tj(int k){
        flag[k]=1;
        for(int i=head[k];i;i=e[i].nex){
            if(flag[e[i].v])continue;
            tj(e[i].v);
            sz[k]+=sz[e[i].v];
            ha[k]+=ha[e[i].v];
        }
        if(k!=1){
            if(!sz[k])ans+=m-1,t++;
            if(sz[k]==1)ans++;
        }
    }
    int main(){
        srand(23333);
        cin>>n>>m;
        for(int i=1,t1,t2;i<=m;i++){
            scanf("%d%d",&t1,&t2);
            add(t1,t2);add(t2,t1);
            e[tot].h=e[tot-1].h=rand()*rand();
        }
        dfs(1,0);
        memset(flag,0,sizeof flag);tj(1);
        sort(ha+1,ha+n+1);
        for(int i=1;i<=n;i++){
            int j=i;
            for(;ha[j+1]==ha[i];j++);
            if(ha[j]==0)continue;
            int len=j-i+1;
            ans=ans+1LL*len*(len-1)/2;
            i=j;
        }
        ans=ans-1LL*t*(t-1)/2;
        cout<<ans<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    ng的ngModel用来处理表单操作
    ionic改tab文字和icon图片的颜色
    ionic安装遇到的一些问题
    ionic运行测试
    安卓sdk安装教程
    ionic教程
    ng 构建
    ng websocket
    ng依赖注入
    Python: 定时器(Timer)简单实现
  • 原文地址:https://www.cnblogs.com/liankewei/p/10696171.html
Copyright © 2020-2023  润新知