zoukankan      html  css  js  c++  java
  • bzoj2730: [HNOI2012]矿场搭建

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2730

    思路:点双缩点

    对于一个点双,如果它不与任何一个割点相连,那它就要建两个出口

    与一个相连,就见一个

    与两个以上相连就不用建

    方案就是每个点双去掉割点的点数之积

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int maxn=1010,maxm=maxn<<1;
    typedef long long ll;
    using namespace std;
    int n,m,now[maxn],son[maxm],pre[maxm],T;
    int low[maxn],dfn[maxn],tim,tot,cas,deg,cnt,num,vis[maxn],ans1,root;bool cut[maxn];
    ll ans2;
    void clear(){
    	memset(now,0,sizeof(now)),memset(low,0,sizeof(low)),memset(dfn,0,sizeof(dfn));
    	memset(cut,0,sizeof(cut)),memset(vis,0,sizeof(vis)),tot=n=tim=T=ans1=0,cas++,ans2=1;
    }
    void add(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;}
    
    void tarjan(int x,int fa){
    	dfn[x]=low[x]=++tim;//printf("%d
    ",x);
    	for (int y=now[x];y;y=pre[y]){
    		if (son[y]==fa) continue;
    		if (!dfn[son[y]]) tarjan(son[y],x),low[x]=min(low[x],low[son[y]]);
    		else{low[x]=min(low[x],dfn[son[y]]);continue;}
    		//printf("fuckpp%d %d
    ",x,son[y]);
    		if (dfn[x]<=low[son[y]]){if (x==root) deg++;else cut[x]=1;}
    	}
    }
    
    void dfs(int x){
    	//printf("%d
    ",x);
    	vis[x]=T;if (cut[x]) return; cnt++;
    	for (int y=now[x];y;y=pre[y]){
    		if (cut[son[y]]&&vis[son[y]]!=T) num++,vis[son[y]]=T;
    		if (!vis[son[y]]) dfs(son[y]);
    	}
    }
    
    int main(){
    	scanf("%d",&m);
    	while (m){
    		clear();
    		for (int i=1,x,y;i<=m;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x),n=max(x,n),n=max(n,y);
    		for (int i=1;i<=n;i++){
    			if (!dfn[i]){tarjan(root=i,0);if (deg>=2) cut[root]=1;}//root要特判,因为要有两个才算割点
    			deg=0;
    		}
    		//for (int i=1;i<=n;i++) {printf("%d %d %d
    ",i,dfn[i],low[i]);if (cut[i]) printf("%d
    ",i);}
    		for (int i=1;i<=n;i++)
    			if (!vis[i]&&!cut[i]){
    				++T,cnt=num=0,dfs(i);//T时间戳,cnt:块的大小,num:块中割点数
    				if (!num) ans1+=2,ans2*=cnt*(cnt-1)/2;
    				if (num==1) ans1++,ans2*=cnt;
    			}
    		printf("Case %d: %d %lld
    ",cas,ans1,ans2);
    		scanf("%d",&m);
    	}
    	return 0;
    }


  • 相关阅读:
    Druid 配置_DruidDataSource参考配置
    Druid 配置 wallfilter
    Druid 配置_配置WebStatFilter
    Druid 配置_StatViewServlet配置
    Druid 配置_StatFilter
    Druid数据库连接池使用
    Spring泛型依赖注入
    java计算代码执行时间
    模板方法在Spring事务中的应用
    maven,阿里云国内镜像,提高jar包下载速度
  • 原文地址:https://www.cnblogs.com/thythy/p/5493481.html
Copyright © 2011-2022 走看看