zoukankan      html  css  js  c++  java
  • bzoj2730(割点+分类讨论)

    把割点删去后,剩下的联通块个数就是答案,方案数就是siz乘一起,但要讨论一些特殊情况,没有割点时答案直接算,一个联通块如果连接多个割点是不需算入答案的;

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn=505;
    struct edg{
        int nxt,u,v;
    }e[maxn<<1];
    int dfn[maxn],low[maxn],ind,is[maxn];
    int last[maxn],t,cas,n,m,vis[maxn],cc,tim;
    ll ans=1,sum,cnt,tmp,w[maxn];
    void add(int x,int y){
        n=max(n,max(x,y));
        ++t;e[t].nxt=last[x];last[x]=t;e[t].v=y;
    }
    void dfs(int x,int fa){
        low[x]=dfn[x]=++ind;
        int child=0;
        for(int i=last[x];i;i=e[i].nxt){
            int v=e[i].v;
            if(v==fa)continue;
            if(!dfn[v]){
                child++;
                dfs(v,x);
                low[x]=min(low[x],low[v]);
                if(fa&&low[v]>=dfn[x]){is[x]=1;++cc;}
                if(child>1&&!fa){is[x]=1;++cc;}
            }
            else low[x]=min(low[x],dfn[v]);
        }
    }
    int solve(int x){
        vis[x]=1;
        int siz=1;
        for(int i=last[x];i;i=e[i].nxt){
            int v=e[i].v;
            if(!vis[v]){
                if(is[v]){
                    if(w[v]!=tim){cnt++;w[v]=tim;}
                }
                else siz+=solve(v);
            }
        }
        return siz;
    }
    int main(){
        while(scanf("%d",&m)!=EOF&&m){
            printf("Case %d: ",++cas);
            memset(last,0,sizeof(last));
            memset(low,0,sizeof(low));
            memset(dfn,0,sizeof(dfn));
            memset(vis,0,sizeof(vis));
            memset(is,0,sizeof(is));
            cc=tim=sum=n=t=ind=0;ans=1;
            int x,y;
            for(int i=1;i<=m;++i){
                scanf("%d%d",&x,&y);
                add(x,y);add(y,x);
            }
            for(int i=1;i<=n;++i){
                if(!dfn[i])dfs(i,0);
            }
            if(!cc){printf("2 %d
    ",n*(n-1)/2);continue;}
            for(int i=1;i<=n;++i)
            if((!vis[i])&&(!is[i])){
                ++tim;
                cnt=0;
                int tmp=solve(i);
                //cout<<cnt<<' '<<tmp<<endl;
                if(cnt<=1){
                    sum++;
                    ans*=tmp;
                }
            }
            printf("%lld %lld
    ",sum,ans);
        }
        return 0;
    } 
  • 相关阅读:
    分布式文件系统技术选型
    .net core 与nginx笔记
    分布式场景
    c printf函数
    c 编程范式
    VS2019 卡顿,甚至卡死
    SQL Server 跨服务器查询
    递归 0到100求和
    moment js 制作倒计时 比较简单
    关于地狱回调的理解
  • 原文地址:https://www.cnblogs.com/dibaotianxing/p/8628594.html
Copyright © 2011-2022 走看看