BZOJ 2730 HNOI2012 矿场搭建 Tarjan

news/2024/10/17 20:18:14/

题目大意:给定一个无向图,要求将一些点设为出口 要求图中删掉任意一个点后剩余的任意一个点都与至少一个出口相连 求最少建多少个出口以及建最少出口的方案数

首先看到割点就是Tarjan搞 但是怎么搞

首先假设我们把所有的点双都缩点 那么我们一定可以得到一棵树 然后我们就会发现

叶子节点(只含有一个割点的点双)必须建 因为叶子节点如果不建 一旦割点被爆就死翘了

非叶节点(含有两个或两个以上的割点的点双)不用建 因为即使一个割点被爆了也可以沿着另一个割点走到一个叶节点

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

如果只有一个点 那么这个点必须建 数据没有卡这个的点所以我没写(其实是我忘写了 然后还过了)

如果有两个或两个以上的点 那么要建两个 一个被爆了还可以走另一个

方案数就是乘法原理的问题了 注意叶节点那里出口不能建在割点上

#include<cstdio>  
#include<cstring>  
#include<iostream>  
#include<algorithm>  
#define M 1010  
using namespace std;  
typedef long long ll;  
struct abcd{  int to,next;  
}table[M];  
int head[M],tot=1;  
int n,m,cases,ans1;  
long long ans2;  
int dpt[M],low[M],cnt,belong[M],stack[M],top;  
inline void Initialize()  
{  memset(head,0,sizeof head);  memset(dpt,0,sizeof dpt);  memset(belong,0,sizeof belong);  tot=1;n=0;ans1=0;ans2=1;  
}  
void Add(int x,int y)  
{  table[++tot].to=y;  table[tot].next=head[x];  head[x]=tot;  
}  
void Tarjan(int x)  
{  int i;  dpt[x]=low[x]=++cnt;  for(i=head[x];i;i=table[i].next)  {  int y=table[i].to;  if(dpt[y])  low[x]=min(low[x],dpt[y]);  else  {  Tarjan(y);  low[x]=min(low[x],low[y]);  if(low[y]>=dpt[x])  belong[x]++;  }  }  
}  
void _Tarjan(int x)  
{  int i;  dpt[x]=low[x]=++cnt;  stack[++top]=x;  for(i=head[x];i;i=table[i].next)  {  int y=table[i].to;  if(dpt[y])  low[x]=min(low[x],dpt[y]);  else  {  _Tarjan(y);  low[x]=min(low[x],low[y]);  if(low[y]>=dpt[x])  {  int t,temp=0,size=0;  do{  t=stack[top--];  if(belong[t]>=2)  ++temp;  ++size;  }while(t!=y);  t=x;  if(belong[t]>=2)  ++temp;  ++size; if(!temp)  ans1+=2,ans2*=size*(size-1)/2;  else if(temp==1)  ans1++,ans2*=size-1;  }  }  }  
}  
int main()  
{  //freopen("2730.in","r",stdin);  int i,x,y;  while(scanf("%d",&m),m)  {  Initialize();  for(i=1;i<=m;i++)  {  scanf("%d%d",&x,&y);  n=max(n,x);  n=max(n,y);  Add(x,y);  Add(y,x);  }  for(i=1;i<=n;i++)  if(!dpt[i])  Tarjan(i);  else  belong[i]++;  memset(dpt,0,sizeof dpt);  for(i=1;i<=n;i++)  if(!dpt[i])  _Tarjan(i);  cout<<"Case "<<++cases<<": ";  cout<<ans1<<' '<<ans2<<endl;  }  
}  



http://www.ppmy.cn/news/248357.html

相关文章

leetcode 165. 比较版本号-java实现

题目所属分类 模拟就可以了 原题链接 给你两个版本号 version1 和 version2 &#xff0c;请你比较它们。 版本号由一个或多个修订号组成&#xff0c;各修订号由一个 ‘.’ 连接。每个修订号由 多位数字 组成&#xff0c;可能包含 前导零 。每个版本号至少包含一个字符。修订…

基于HAL库的STM32的单定时器的多路输入捕获测量脉冲频率(外部时钟实现)

目录 写在前面 一般的做法&#xff08;定时器单通道输入捕获) 以外部时钟的方式(高低频都适用) 测试效果 写在前面 STM32的定时器本身有输入捕获的功能。可选择双端捕获&#xff0c;上升沿捕获或者是下降沿捕获。对应捕获频率来说,连续捕获上升沿或下降沿的时间间隔就是其脉…

编译LineageOS-20并输入Pixel 2XL

编译LineageOS-20并输入Pixel 2XL 2023-6-6 hongxi.zhu 目录 编译LineageOS-20并输入Pixel 2XL一、编译LineageOS-201. 准备工作1.1 安装platform-tools1.2 安装必要的依赖1.3 创建相关目录1.4 下载repo可执行文件1.5 配置 2. 拉取源码2.1 初始化仓库2.2 同步源码 3. 编译源码3…

【算法】--- 几分钟了解直接选择排序(排序中最简单的排序)+快排(解决一切的优质算法)(中)

文章目录 前言&#x1f31f;一、常见的排序算法&#xff1a;&#x1f31f;二、选择排序---直接选择排序&#xff1a;&#x1f30f;2.1.1 基本思想&#xff1a;&#x1f30f;2.1.2 直接选择排序:&#x1f30f;2.1.3 直接选择排序的特性总结&#xff1a;&#x1f30f;2.1.4 思路&…

SpringBoot+MyBatisplus搭建校园新闻平台——已开源

概述 开发背景 校园新闻平台是以新闻宣传机构的在线信息发布需求为基础&#xff0c;随着数字化和信息化的快速发展&#xff0c;校园新闻在校园内的传播和沟通中变得越来越重要。学校需要一个有效的管理系统来整合、发布和传播校园新闻&#xff0c;以满足师生、校友和其他利益…

Java的引用

一、概述 其实java有4种引用&#xff0c;4种可分为强、软、弱、虚。我们将从这四个方面入手进行介绍。 二、强引用 首先看到我们有一个类叫M&#xff0c;在这个类里我重写了一个方法叫finalize()&#xff0c;我们可以看到这个方法是已经被废弃的方法&#xff0c;为什么要重写…

北大教授一年时间制作的Java300集课程,我免费分享给你~

Java是一门面向对象的编程语言&#xff0c;不仅吸收了C语言的各种优点&#xff0c;还摒弃了C里难以理解的多继承、指针等概念&#xff0c;因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表&#xff0c;极好地实现了面向对象理论&#xff0…

达内java面试题集_达内java面试题

JAVA面试题-COREJAVA部分1&#xff0e;在main(String[] args)方法内是否可以调用一个非静态方法&#xff1f;答案&#xff1a;不能2&#xff0e;同一个文件里是否可以有两个public类&#xff1f;答案&#xff1a;不能3&#xff0e;方法名是否可以与构造器的名字相同&#xff1f…