zoukankan      html  css  js  c++  java
  • BZOJ2730 矿场搭建

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2730

    基本思路,注意到n非常的小,所以暴力即可。

    首先显然我们要找出所有的割点,$O(n^2)$并查集。

    我们将所有的割点删除,然后将剩余的边用并查集维护,化为很多个联通块。

    有三种情况:

    1.联通块和一个割点相连,这种情况下显然只能在当前联通块里任选一个点建一个逃生点。

    2.与两个割点相连,这种情况下不用建逃脱点因为他只能割掉其中一个割点。

    3.没有割点,至少建两个(任选两个点),因为有可能逃生点被破坏了,所以为两个。

    至于情况数,因为同一联通块的点没有不同,所以直接乘起来。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <set>
    
    #define N 510
    #define p E[i].x
    #define LL long long
    
    using namespace std;
    
    struct edge{
        int x,to;
    }E[N<<1];
    
    int m,n,g[N],totE,fa[N],cnt[N],siz[N];
    set<int> G[N];
    bool cut[N];
    
    inline void addedge(int x,int y){
        E[++totE]=(edge){y,g[x]}; g[x]=totE;
        E[++totE]=(edge){x,g[y]}; g[y]=totE;
    }
    
    int find(int x){
        if(fa[x]!=x) fa[x]=find(fa[x]);
        return fa[x];
    }
        
    void add(int x,int y){
        int r1=find(x),r2=find(y);
        if(r1!=r2) fa[r2]=r1;
    }
    
    bool check(int x){
        for(int i=1;i<=n;i++) fa[i]=i;
        for(int i=2;i<=totE;i+=2)
            if(E[i].x!=x&&E[i^1].x!=x) add(E[i].x,E[i^1].x);
        int tmp=0;
        for(int i=1;i<=n;i++){
            if(i==x) continue;
            if(!tmp) tmp=find(i);
            if(find(i)!=tmp) return 1;
        }
        return 0;
    }
    
    int main(){
    
        int caset=0;
        while(scanf("%d",&m)==1){
            if(!m) break;
            for(int i=1;i<=n;i++){
                cut[i]=0;
                siz[i]=g[i]=cnt[i]=0;
                G[i].clear();
            }
            printf("Case %d: ",++caset);
            totE=1; n=0;
            for(int i=1,x,y;i<=m;i++){
                scanf("%d%d",&x,&y);
                addedge(x,y);
                n=max(n,x); n=max(n,y);
            }
            bool fl=0;
            for(int i=1;i<=n;i++)
                if(check(i)) cut[i]=1,fl=1;
            if(!fl){
                printf("%d %lld
    ",2,((n-1)*(LL)n)/2);
                continue;
            }
            for(int i=1;i<=n;i++) fa[i]=i;
            for(int i=2;i<=totE;i+=2)
                if(!cut[E[i].x]&&!cut[E[i^1].x]) add(E[i].x,E[i^1].x);
            for(int x=1;x<=n;x++){
                siz[find(x)]++;
                if(!cut[x]) continue;
                for(int i=g[x];i;i=E[i].to)
                    if(!cut[p]) G[find(p)].insert(x);
            }
            int ans=0;
            LL ansv=1;
            for(int i=1;i<=n;i++){
                if(cut[i]) continue;
                if(find(i)!=i) continue;
                if(G[i].size()<2){
                    ans++;
                    ansv*=siz[i];
                }
            }
            printf("%d %lld
    ",ans,ansv);
        }
    }
    View Code
  • 相关阅读:
    阿里巴巴
    实用得 JS 代码
    C#获得当前插入数据的ID
    “职场五魅”助你成功
    SQL2005导入导出数据库方法集合
    VS05里checkboxlist用JS获取 value值
    sql 去除html标签函数
    百度新闻搜索结果页的采集
    把表中的某个字段格式如:2,3,4的数据分别插入到另一个表中
    jquery 定位元素并获取数据
  • 原文地址:https://www.cnblogs.com/lawyer/p/4552007.html
Copyright © 2011-2022 走看看