zoukankan      html  css  js  c++  java
  • [题解](tarjan割点/点双)luogu_P3225_矿场搭建

    首先和割点有关,求割点,然后这些割点应该把这个图分成了多个点双,可以考虑点双的缩点,假如缩点做的话我们要分析每个点双的性质和贡献

    先拿出一个点双来,如果它没有连接着割点,那么至少要建两个,以防止其中一个塌陷,

    如果它连接着一个割点,那么需要建一个,因为可以通过割点到其他点双,或者割点塌陷走这个点双中的出口

    如果它连接着两个以上的割点,那么不需要建,因为可以随意到达其他点双。

    事实上没必要缩点,只要dfs每个点双,类似于联通块(题解中直接说联通块容易有歧义)染色,记录点数和连接的割点数目

    对于情况1,方案贡献C(点数,2)=(点数)*(点数-1)/2;

    情况2贡献就是点数。每次ans2*=贡献

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=509;
    int n,m,num,tot,deg,ans1,T,root;long long ans2;
    struct node{
        int v,nxt;
    }e[maxn<<1];
    int head[maxn],cnt;
    void add(int u,int v){
        e[++cnt].v=v;e[cnt].nxt=head[u];head[u]=cnt;
    }
    int dfn[maxn],low[maxn],vis[maxn];
    bool cut[maxn];
    inline void init(){
        memset(head,0,sizeof(head));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(cut,0,sizeof(cut));
        memset(vis,0,sizeof(vis));
        cnt=tot=n=ans1=T=0;ans2=1;
    }
    void tarjan(int x,int fa){
        dfn[x]=low[x]=++tot;
        for(int i=head[x];i;i=e[i].nxt){
            int y=e[i].v;
            if(!dfn[y]){
                tarjan(y,x);
                low[x]=min(low[x],low[y]);
                if(low[y]>=dfn[x]){
                    if(x==root)deg++;
                    else cut[x]=1;
                }
            }
            else if(y!=fa)low[x]=min(low[x],dfn[y]);
        }
    }
    void dfs(int x){
        vis[x]=T;
        if(cut[x])return;
        cnt++;
        for(int i=head[x];i;i=e[i].nxt){
            int y=e[i].v;
            if(cut[y] && vis[y]!=T)num++,vis[y]=T;//统计割点数 
            if(!vis[y])dfs(y);
        }
    }
    int main(){int t=0;
        while(1){
            scanf("%d",&m);if(m==0)break;
            init();
            for(int i=1,u,v;i<=m;i++){
                scanf("%d%d",&u,&v);
                add(u,v);add(v,u);n=max(n,max(v,u));
            }
            for(int i=1;i<=n;i++){
                if(!dfn[i])tarjan(root=i,0);
                if(deg>=2)cut[root]=1;
                deg=0;
            }
            for(int i=1;i<=n;i++)
            if(!vis[i] && !cut[i]){
                T++;cnt=num=0;
                dfs(i);
                if(!num)ans1+=2,ans2*=cnt*(cnt-1)/2;
                if(num==1)ans1++,ans2*=cnt;
            }
            printf("Case %d: %d %lld
    ",++t,ans1,ans2);
        }
    }
  • 相关阅读:
    什么是高大上项目?
    spring事务回滚问题
    分布式ActiveMQ集群
    基于bootstarp的Dailog
    js实现的笛卡尔乘积-商品发布
    MemcachedClient 使用说明
    docker centos容器无法yum
    java Graphics2D 画图
    spring boot 访问外部http请求
    JSON 数据重复 出现$ref
  • 原文地址:https://www.cnblogs.com/superminivan/p/10822479.html
Copyright © 2011-2022 走看看