题目链接

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. axios的get请求无法设置Content-Type

    最近在与后端的项目对接中,接口工具使用了axios这个东西.怎么说那 ,反正有很多坑,在后端的请求中要设置GET 请求中要设置header中的Content-Type为application/json ...

  2. Arcgis python输出当前窗口

    import arcpy mxd = arcpy.mapping.MapDocument("CURRENT") mxdfile=arcpy.GetParameterAsText(0 ...

  3. LC 813. Largest Sum of Averages

    We partition a row of numbers A into at most K adjacent (non-empty) groups, then our score is the su ...

  4. android Api操作SQLite数据库的示例代码

    import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.databa ...

  5. mock的使用

    mock的重要性 mock就是对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建的方法.项目开发和测试过程中,遇到以下的情况时,就需要模拟结果返回. 1.当另一方接口或服务还未完成,阻碍项 ...

  6. C# VS预生成事件命令行 和 生成后事件命令行

    宏 说明 $(ConfigurationName) 当前项目配置的名称(例如,“Debug|Any CPU”). $(OutDir) 输出文件目录的路径,相对于项目目录.这解析为“输出目录”属性的值. ...

  7. CentOS 7 最小化安装后的注意事项

    http://blog.csdn.net/f_srion/article/details/54910943 在VM虚拟机中安装CentOS 7 时 有时候顾虑到电脑硬件性能,我们需要最小化安装,而最小 ...

  8. linux简单命令8---软件包安装

    1:使用yum安装,它不能包查询和包校验.它安装的是RPM格式文件.没有yum文件 ---------------------------------------------------------- ...

  9. lumen怎么得到当前Uri的控制器、Action、路由规则

    <?php namespace App\Http\Controllers; class HelloController extends Controller { public function ...

  10. linux硬件驱动

    今天被问到了一个新问题:linux需不需要安装驱动,就像windows装完系统之后需要安装最新驱动一样? 说实话以前真没想过,都是装完系统update一下就直接用了. 谷歌了一下,发现其实也是需要安装 ...