题目链接

https://www.luogu.org/problemnew/show/P2860

https://www.lydsy.com/JudgeOnline/problem.php?id=1718

分析

首先这题目的意思就是让任意两点之间至少有两条没有重复道路的路径,很显然,如果这个图不存在桥,就一定满足上述条件。

于是我们就是要求使这个图不存在桥需要连接的最小边数

如果把桥从图中去掉,很显然剩余的联通块中任意两点之间至少有两条没有重复道路的路径(当然也可能不是联通块而是孤立的点),对答案不会产生贡献,我们不妨就将这些联通块缩点,于是就原来的图就变成了一颗树。

然后思考题目要求,当每个节点的度为2时任意两点之间至少有两条没有重复道路的路径,因为此时任意节点都有两条不同道路可走,于是用贪心的思想我们让度数为\(1\)的先互相连接,所以计算出树中的叶节点个数\(x\),\(\lceil\frac{x}{2}\rceil\)就是答案

注意

好象没什么注意的,不过我太菜把\(edge [j] .to\)写成\(edge [i] .to\)查了好久的错

代码


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cctype>
#include <cmath>
#include <map>
#include <queue>
#define ll long long
#define ri register int
using namespace std;
const int maxn=5005;
const int maxm=10005;
const int inf=0x7fffffff;
template <class T>inline void read(T &x){
x=0;int ne=0;char c;
while(!isdigit(c=getchar()))ne=c=='-';
x=c-48;
while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
x=ne?-x:x;
return ;
}
struct Edge{
int ne,to;
}edge[maxm<<1];
int h[maxn],num_edge=0;
inline void add_edge(int f,int to){
edge[++num_edge].ne=h[f];
edge[num_edge].to=to;
h[f]=num_edge;
return ;
}
int n,m;
int dfn[maxn],low[maxn],tot=0;
bool bridge[maxm];
void tarjan(int now,int in_edge){//所在边的标号
int v;dfn[now]=low[now]=++tot;
for(ri i=h[now];i;i=edge[i].ne){
v=edge[i].to;
if(!dfn[v]){
tarjan(v,i);
low[now]=min(low[now],low[v]);
if(dfn[now]<low[v]){
bridge[i]=bridge[i^1]=true;//是桥
bb++;
}
}
else if(i!=(in_edge^1)){//如果不是在同一条无向边的对应边
low[now]=min(low[now],dfn[v]);
}
}
return ;
}
int num=0;//联通块的数量
int in_block[maxn];//各点所在联通块的标号
bool g[maxn][maxn];//重构后的图(储存)
void Contraction_Point(int now){//缩点
int v;in_block[now]=num;
for(ri i=h[now];i;i=edge[i].ne){
v=edge[i].to;
if(!bridge[i]&&!in_block[v]){
Contraction_Point(v);
}
}
return ;
}
int du[maxn];
inline void solve(){
int ans=0,x,y;
memset(g,0,sizeof(g));
for(ri i=1;i<=n;i++){
x=in_block[i];
for(ri j=h[i];j;j=edge[j].ne){
y=in_block[edge[j].to]; //太坑了
g[x][y]=g[y][x]=1;
}
}
memset(du,0,sizeof(du));
for(ri i=1;i<=num;i++){
for(ri j=1;j<=num;j++){
if(i!=j&&g[i][j]){du[j]++;
}
}
}
for(ri i=1;i<=num;i++){
if(du[i]==1)ans++;
}
printf("%d",(int)ceil(ans/double(2)));
return ;
}
int main(){
int x,y;
read(n),read(m);
num_edge=1;
for(ri i=1;i<=m;i++){
read(x),read(y);
add_edge(x,y);
add_edge(y,x);
}
memset(bridge,0,sizeof(bridge));
tarjan(1,0);
memset(in_block,0,sizeof(in_block));
for(ri i=1;i<=n;i++){
if(!in_block[i]){
num++;
Contraction_Point(i);
}
}
solve();
return 0;
}

luogu题解 P2860[USACO冗余路径Redundant Paths] 缩点+桥的更多相关文章

  1. 洛谷 P2860 [USACO06JAN]冗余路径Redundant Paths 解题报告

    P2860 [USACO06JAN]冗余路径Redundant Paths 题目描述 为了从F(1≤F≤5000)个草场中的一个走到另一个,贝茜和她的同伴们有时不得不路过一些她们讨厌的可怕的树.奶牛们 ...

  2. 【luogu P2860 [USACO06JAN]冗余路径Redundant Paths】 题解

    题目链接:https://www.luogu.org/problemnew/show/P2860 考虑在无向图上缩点. 运用到边双.桥的知识. 缩点后统计度为1的点. 度为1是有一条路径,度为2是有两 ...

  3. luogu P2860 [USACO06JAN]冗余路径Redundant Paths

    题目描述 In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1- ...

  4. luogu P2860 [USACO06JAN]冗余路径Redundant Paths |Tarjan

    题目描述 In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1. ...

  5. LUOGU P2860 [USACO06JAN]冗余路径Redundant Paths (双联通,缩点)

    传送门 解题思路 刚开始是找的桥,后来发现这样不对,因为一条链就可以被卡.后来想到应该缩点后找到度数为1 的点然后两两配对. #include<iostream> #include< ...

  6. 洛谷P2860 [USACO06JAN]冗余路径Redundant Paths(tarjan求边双联通分量)

    题目描述 In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1. ...

  7. P2860 [USACO06JAN]冗余路径Redundant Paths tarjan

    题目链接 https://www.luogu.org/problemnew/show/P2860 思路 缩点,之后就成了个树一般的东西了 然后(叶子节点+1)/2就是答案,好像贪心的样子,lmc好像讲 ...

  8. 洛谷P2860 [USACO06JAN]冗余路径Redundant Paths

    题目描述 In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1. ...

  9. (精)题解 guP2860 [USACO06JAN]冗余路径Redundant Paths

    (写题解不容易,来我的博客玩玩咯qwq~) 该题考察的知识点是边双连通分量 边双连通分量即一个无向图中,去掉一条边后仍互相连通的极大子图.(单独的一个点也可能是一个边双连通分量) 换言之,一个边双连通 ...

随机推荐

  1. mybatis 批量将list数据插入到数据库

    随着业务需要,有时我们需要将数据批量添加到数据库,mybatis提供了将list集合循环添加到数据库的方法.具体实现代码如下: 1.mapper层中创建 insertForeach(List < ...

  2. Qt串口通信专题教程

    查看以前的教程:Qt编写串口通信程序全程图文讲解 查看Wincom和Lincom介绍:Qt跨平台串口通信软件Wincom与Lincom 下载软件,文档和源码:资源下载 ——————————————20 ...

  3. How to use reminder feature of the outlook

    https://support.office.com/en-us/article/set-or-remove-reminders-7a992377-ca93-4ddd-a711-851ef359792 ...

  4. javascript对象属性和数组的访问

    javascript对象属性的访问 假如有对象test:var test = {  "a":1,  "b":2};直接访问对象test的属性a的值,有两种方法: ...

  5. leetcode1284 转化为全零矩阵的最少反转次数

    m == mat.length n == mat[0].length 1 <= m <= 3 1 <= n <= 3 mat[i][j] 是 0 或 1 . BFS, 代码来自 ...

  6. 框架-Eureka:百科

    ylbtech-框架-Eureka:百科 1.返回顶部 1. Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中 ...

  7. Hibernate3疑惑解决

    1.session的get()和load()有什么区别?     # get()如果没有找到持久化类返回null,有可能导致空指针异常.     # load()如果没有找到持久化类直接抛出异常.   ...

  8. 006-top查看计算机信息

    1.使用top命令基本信息 us:用户态使用的cpu时间比sy:系统态使用的cpu时间比ni:用做nice加权的进程分配的用户态cpu时间比id:空闲的cpu时间比wa:cpu等待磁盘写入完成时间hi ...

  9. Canal——增量同步MySQL数据到ElasticSearch

    1.准备 1.1.组件 JDK:1.8版本及以上: ElasticSearch:6.x版本,目前貌似不支持7.x版本:       Kibana:6.x版本:     Canal.deployer:1 ...

  10. Java日志体系(四)slf4j

    1.1 简介 与commons-logging相同,slf4j也是一个通用的日志接口,在程序中与其他日志框架结合使用,并对外提供服务. Simple Logging Facade for Java简称 ...