• 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;
    }


  • 相关阅读:
    哲理故事
    ajaxToolkit发布之后出错!说未能加载文件或程序集!
    一个沉重的教训!!!
    ValidatorCallout真的是太酷了!
    GridView放在UpdatePanle里面模板列取值!
    Prototype学习笔记之-Ajax.Request
    数据分类重排!
    SQL SERVER 2005 sa登录失败!
    flex应该学到什么程度
    jquery dataTable的学习
  • 原文地址:https://www.cnblogs.com/thythy/p/5493481.html
Copyright © 2020-2023  润新知