zoukankan      html  css  js  c++  java
  • bzoj 2730: [HNOI2012]矿场搭建【tarjan】

    先tarjan找割点和点双连通分量,然后对一个点双,如果没有割点,那么需要建立两个出口(割掉一个另一个备用);如果只有一个割点,出口可以设立在任意一个非割点的地方;如果有两个及以上个割点,就不用建出口(可以直接到达其他联通块)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=1005;
    int n,m,h[N],cnt,cas,ans1,dfn[N],low[N],tot,bl[N],s[N],top;
    long long ans2;
    struct qwe
    {
        int ne,to;
    }e[N];
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void add(int u,int v)
    {
    	cnt++;
        e[cnt].ne=h[u];
        e[cnt].to=v;
        h[u]=cnt;
    }
    void tarjan(int u)
    {
        dfn[u]=low[u]=++tot;
        for(int i=h[u];i;i=e[i].ne)
        {
            if(dfn[e[i].to])
                low[u]=min(low[u],dfn[e[i].to]);
            else
            {
                tarjan(e[i].to);
                low[u]=min(low[u],low[e[i].to]);
                if(low[e[i].to]>=dfn[u])
                    bl[u]++;
            }
        }
    }
    void tarjan2(int u)
    {
        dfn[u]=low[u]=++tot;
        s[++top]=u;
        for(int i=h[u];i;i=e[i].ne)
        {
            if(dfn[e[i].to])
                low[u]=min(low[u],dfn[e[i].to]);
            else
            {
                tarjan2(e[i].to);
                low[u]=min(low[u],low[e[i].to]);
                if(low[e[i].to]>=dfn[u])
                {
                    int t,temp=0,size=0;
                    do
                    {
                        t=s[top--];
                        if(bl[t]>=2)
                            ++temp;
                        ++size;
                    }
    				while(t!=e[i].to);
                    t=u;
                    if(bl[t]>=2)
                        ++temp;
                    ++size;
                    if(!temp)
                        ans1+=2,ans2*=size*(size-1)/2;
                    else if(temp==1)
                        ans1++,ans2*=size-1;
                }
            }
        }
    }
    int main()
    {
        while(1)
        {	
    		m=read();
    		if(!m)
    			break;
            memset(h,0,sizeof(h));
            memset(dfn,0,sizeof(dfn));
            memset(bl,0,sizeof(bl));
            cnt=1;n=0;ans1=0;ans2=1;
            for(int i=1;i<=m;i++)
            {
                int x=read(),y=read();
                n=max(n,max(x,y));
                add(x,y),add(y,x);
            }
            for(int i=1;i<=n;i++)
                if(!dfn[i])
                    tarjan(i);
                else
                    bl[i]++;
            memset(dfn,0,sizeof(dfn));
            for(int i=1;i<=n;i++)
                if(!dfn[i])								
                    tarjan2(i);
    		printf("Case %d: %d %lld
    ",++cas,ans1,ans2);
        }
    	return 0;
    }
    
  • 相关阅读:
    与大神聊天1h
    《海上钢琴师》观后感
    《小王子》读书笔记
    Joining Data with dplyr in R
    SQL学习笔记1
    电影《受益人》观后感
    markdown文本编辑学习笔记2
    importing-cleaning-data-in-r-case-studies
    一个测试人员的工作该怎么开展
    测试总结报告
  • 原文地址:https://www.cnblogs.com/lokiii/p/9385250.html
Copyright © 2011-2022 走看看