题目链接

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. koa 项目实战(九)passport验证token

    1.安装模块 npm install koa-passport -D npm install passport-jwt -D 2.解析token 根目录/config/passport.js cons ...

  2. P5020 货币系统

    P5020 货币系统 题解 仔细分析... 这道题其实就是求所给数组中有多少个数字不能被该数组中的数字自由组合表示出来 比如样例1 3,10 不能被该集合里的数字表示出来,所以他们组成目标集合 6=3 ...

  3. Android 网络请求Retrofit + RxJava

    一.背景 经常看到项目用Retrofit+RxJava+RxAndroid的框架,为了看懂项目的结构.现在来了解一下,Retrofit: Retrofit是Square 公司开发的一款正对Androi ...

  4. flutter Android打包

    以下内容均是在mac版本电脑上的操作 1.生成签名 //根目录执行以下命令 keytool -genkey -v -keystore ~/sign.jks -keyalg RSA -keysize 2 ...

  5. PCL中有哪些可用的PointT类型(1)

    博客转载自:http://www.pclcn.org/study/shownews.php?lang=cn&id=266 为了涵盖能想到的所有可能的情况,PCL中定义了大量的point类型.下 ...

  6. Redis高级特性及应用场景

    Redis高级特性及应用场景 redis中键的生存时间(expire) redis中可以使用expire命令设置一个键的生存时间,到时间后redis会自动删除它. 过期时间可以设置为秒或者毫秒精度. ...

  7. 一百二十七:CMS系统之添加轮播图前后台逻辑

    后台逻辑 模型 from exts import dbfrom datetime import datetime class BannerModel(db.Model): __tablename__ ...

  8. intellij idea如何将web项目打成war包

    1.点击[File]->[Project Structure]菜单(或使用Shift+Ctrl+Alt+S快捷键),打开[Project Structure]窗口.如下图: 2.在[Projec ...

  9. [CDH] Redis: Remote Dictionary Server

    基本概念 一.安装 Redis: Remote Dictionary Server 远程字典服务 使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种 ...

  10. vue cli创建typescript项目

    使用最新的Vue CLI @vue/cli创建typescript项目,使用vue -V查看当前的vue cli版本 安装命令 npm install -g @vue-cli 创建项目 vue cre ...