首页 > 其他分享 >洛谷P3225 [HNOI2012]矿场搭建

洛谷P3225 [HNOI2012]矿场搭建

时间:2022-10-27 14:58:38浏览次数:91  
标签:cut 洛谷 vis int sum 割点 HNOI2012 low P3225

SLOJ H7136. 「HNOI2012」矿场搭建

题目描述

煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。

请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。

输入格式

输入文件有若干组数据,每组数据的第一行是一个正整数 N(N<=500),表示工地的隧道数,接下来的 N 行每行是用空格隔开的两个整数 S 和 T,表示挖 S 与挖煤点 T 由隧道直接连接。输入数据以 0 结尾。

输出格式

输入文件中有多少组数据,输出文件 output.txt 中就有多少行。每行对应一组输入数据的 结果。其中第 i 行以 Case i: 开始(注意大小写,Case 与 i 之间有空格,i 与:之间无空格,: 之后有空格),其后是用空格隔开的两个正整数,第一个正整数表示对于第 i 组输入数据至少需 要设置几个救援出口,第二个正整数表示对于第 i 组输入数据不同最少救援出口的设置方案总 数。输入数据保证答案小于 264。输出格式参照以下输入输出样例。

输入输出样例

输入 #1
9
1  3
4  1
3  5
1  2
2  6
1  5
6  3
1  6
3  2
6
1  2
1  3
2  4
2  5
3  6
3  7
0
输出 #1
Case 1: 2 4
Case 2: 4 1

说明/提示

Case 1 的四组解分别是 (2,4)(2,4),(3,4)(3,4),(4,5)(4,5),(4,6)(4,6);

Case 2 的一组解为 (4,5,6,7)(4,5,6,7)。

对于每组数据,设 mm 为各组 S, TS,T 中最大值,则有:

  • 1≤m≤103
  • 各组 S,,T 构成的集合V=[1,m]∩Z。
  • V中任意两点连通。

思路:肯定跟割点逃不出关系(蒟蒻勉强会一点tarjan,且容我恶补一波)还有组合数学与点双(再容我恶补一波)其实点双与割点本来就容易一起想到,每个点双之中都需要两个出口,方案数就用tarjan求完割点后用dfs遍历一遍连通块然后乘法原理就出来了

无非就是三种情况:

1.叶子节点(只含有一个割点的点双)必须建,叶子节点如果不建,割点塌了就没出口了

2.非叶节点(含有两个或两个以上的割点的点双)不用建,即使一个割点塌了也可以沿着另一个割点走到一个叶节点(即有出口的地方)

3.还有一种情况就是整个联通块都是点双(即不含割点的点双)这样我们讨论点双的大小

#include<bits/stdc++.h>
using namespace std;
struct edge{
    int u,v,ne;
}e[1010];
int n,m,sum,cnt,dfncnt,tmp,root,t,cases,h[1010],dfn[1010],low[1010],vis[1010];
bool cut[1010];
void add(int u,int v){
    sum++;
    e[sum].u = u;
    e[sum].v = v;
    e[sum].ne = h[u];
    h[u] = sum;
}
void tarjan(int u,int fa){
    dfn[u] = low[u] = ++dfncnt;
    for(int i = h[u];i;i = e[i].ne){
        int v = e[i].v;
        if(!dfn[v]){
            tarjan(v,u);
            low[u] = min(low[u],low[v]);
            if(low[v]>=dfn[u]){
                if(u==root) tmp++;
                else cut[u] = true;
            }
        }else if(v!=fa) low[u] = min(low[u],dfn[v]);
    }
}
void dfs(int x){
    vis[x] = t;
    if(cut[x]) return;
    cnt++;
    for(int i = h[x];i;i = e[i].ne){
        int v = e[i].v;
        if(cut[v]&&vis[v]!=t){
            sum++;
            vis[v] = t;
        }
        if(!vis[v]) dfs(v);
    }
}
int main(){
    scanf("%d",&m);
    while(m){
        long long ans1 = 0,ans2 = 1;
        memset(h,0,sizeof(h));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(cut,0,sizeof(cut));
        memset(vis,0,sizeof(vis));
        cnt = dfncnt = n = t = 0;
        for(int i = 1;i<=m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            n = max(n,max(x,y));
            add(x,y);add(y,x);
        }
        for(int i = 1;i<=n;i++){
            if(!dfn[i]) tarjan(root = i,0);
            if(tmp>=2) cut[root] = 1;
            tmp = 0;
        }
        for(int i = 1;i<=n;i++)
            if(!vis[i]&&!cut[i]){
                t++;
                cnt = sum = 0;
                dfs(i);
                if(!sum) ans1+=2,ans2*=cnt*(cnt-1)/2;
                if(sum==1) ans1++,ans2*=cnt;
            }
        printf("Case %d: %lld %lld\n",++cases,ans1,ans2);
        scanf("%d",&m);
    }
    return 0;
}

综上所述,我是蒟蒻

2022-10-27 14:47:21

标签:cut,洛谷,vis,int,sum,割点,HNOI2012,low,P3225
From: https://www.cnblogs.com/cztq/p/16832207.html

相关文章

  • 洛谷 P8595 「KDOI-02」一个网的路 蓝 题解
    定义树形\(DP\),这个挺明显的,我认为\(DP\)让读者理解的最重要的一步是:定义。所以我先详细说明\(f\)数组的定义,至于为什么这么定义后面再讲。\(f_{u,type}\),其中\(......
  • 洛谷 P3592
    首先不难发现最终答案中只会出现\(c_i\)中的数,所以可以将\(c_i\)离散化。设\(f_{i,j,k}\)表示区间\([l,r]\),最小值不小于\(k\)的最大收益,\(cnt_{i,j}\)表示区间......
  • 洛谷P1021题解
    原题P1021[NOIP1999提高组]邮票面值设计思路概述题意分析给定两个整数\(N,K(N+K≤15)\),设计\(K\)种邮票面值\(\{a_1,a_2\dotsa_K\}\),并用共\(N\)张上述邮票......
  • 洛谷P1064题解
    原题P1064[NOIP2006提高组]金明的预算方案思路概述题意分析给定一个体积为\(n\)的背包和\(m\)个物品。每个物品通过\((\text{价值},\text{体积})\)的形式表......
  • 洛谷 P7003
    考虑当左端点固定时,区间的\(\&\)和至多有\(\logw\)种,因为\(1\)的数量是单调不升的。所以我们可以枚举区间左端点\(i\),然后ST表预处理区间\(\&\)和+二分求出......
  • 洛谷P2512 [HAOI2008]糖果传递
    SLOJP1117.糖果传递题目描述有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为11。输入格式小朋友个数n,下面n行ai​......
  • 洛谷 P6453
    设第\(i\)列高\(h_i\),建立序列\(h_i\)的小根笛卡尔树,然后树形DP。发现这样就将原来不规整的图形剖分成若干个矩形:我们发现,这样构成的若干个矩形正好对应小根笛卡......
  • 洛谷优秀油猴插件推荐
    前言转载自眭然的博客,有改编和新增下载链接油猴zip1.先打开edge浏览器的扩展(其他浏览器应该也可以加扩展,不过edge最好)2.打开开发者模式和允许来自其他应用商店的......
  • 洛谷 P6223
    树形DP完全不会。。首先将题目条件改一下:每个人有\(x-v_i\)块钱,要求使所有人的钱数非负的最小操作次数。注意到对于节点\(u\),在子树\(u\)内至多操作\(siz_u-1\)......
  • BZOJ 2733: [HNOI2012]永无乡
    题目链接:​​传送门​​​Description永无乡包含n座岛,编号从1到n,每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用1到n来表示。某些岛之间......