Luogu2860 [USACO06JAN]冗余路径Redundant Paths

\(\verb|Luogu2860 [USACO06JAN]冗余路径Redundant Paths|\)

给定一个连通无向图,求至少加多少条边才能使得原图变为边双连通分量

\(1\leq n\leq5000,\ n-1\leq m\leq10^4\)

tarjan



边双无疑不用考虑,于是就可以边双缩点成一棵树

令现在要连的边为 \((u,\ v)\) ,点集 \(\{u->lca(u,\ v),\ v->lca(u,\ v)\}\) 将会变为一个新的点双,可以将他们看为一个新的点

可以贪心地连边使得每次连边后,不复存在的点尽量多,当只剩一个点时,原图就变成了一个双连通分量

如果 \(u\) 为非叶节点,显然不如将 \(u\) 子树中的一点 \(u‘\) 与 \(v\) 连接,于是 \(u,\ v\) 均为叶节点

若 \(lca(u,\ v)\) 为 \(root\) ,将会消去两个叶节点,否则只会消去一个叶节点,因此每次选择 \(lca(u,\ v)\) 为 \(root\) 的两个点,答案即为 \(叶节点的个数\lfloor\frac{\verb|叶节点的个数|+1}{2}\rfloor\)

时间复杂度 \(O(n+m)\)

代码

#include <bits/stdc++.h>
using namespace std;

#define nc getchar()
const int maxn = 5010;
int n, m, tot, h[maxn], bl[maxn], dfn[maxn], low[maxn], deg[maxn]; bool vis[maxn], cut[maxn << 1];
struct edges {
  int nxt, to;
  edges(int x = 0, int y = 0) : nxt(x), to(y) {}
} e[maxn << 1];

inline int read() {
  int x = 0; char c = nc;
  while (c < 48) c = nc;
  while (c > 47) x = x * 10 + c - 48, c = nc;
  return x;
}

void addline(int u, int v) {
  static int cnt = 1;
  e[++cnt] = edges(h[u], v), h[u] = cnt;
}

void tarjan(int u, int f) {
  static int now;
  dfn[u] = low[u] = ++now;
  for (int i = h[u]; i; i = e[i].nxt) {
    int v = e[i].to;
    if (!dfn[v]) {
      tarjan(v, u);
      low[u] = min(low[u], low[v]);
      if (dfn[u] < low[v]) cut[i] = cut[i ^ 1] = 1;
    } else if (v != f) {
      low[u] = min(low[u], dfn[v]);
    }
  }
}

void dfs(int u) {
  vis[u] = 1, bl[u] = tot;
  for (int i = h[u]; i; i = e[i].nxt) {
    int v = e[i].to;
    if (!cut[i] && !vis[v]) dfs(v);
  }
}

int main() {
  n = read(), m = read();
  for (int i = 1; i <= m; i++) {
    int u = read(), v = read();
    addline(u, v), addline(v, u);
  }
  tarjan(1, 0);
  for (int i = 1; i <= n; i++) {
    if (!vis[i]) tot++, dfs(i);
  }
  for (int u = 1; u <= n; u++) {
    for (int i = h[u]; i; i = e[i].nxt) {
      int v = e[i].to;
      if (bl[u] != bl[v]) deg[bl[v]]++;
    }
  }
  int ans = 0;
  for (int i = 1; i <= tot; i++) {
    ans += deg[i] == 1;
  }
  printf("%d", (ans + 1) >> 1);
  return 0;
}

原文地址:https://www.cnblogs.com/Juanzhang/p/10375244.html

时间: 2024-10-09 21:42:26

Luogu2860 [USACO06JAN]冗余路径Redundant Paths的相关文章

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

题目描述 In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1..F) to another field, Bessie and the rest of the herd are forced to cross near the Tree of Rotten Apples. The cows are now tired of often being forced to t

[USACO06JAN]冗余路径Redundant Paths(缩点)

为了从F(1≤F≤5000)个草场中的一个走到另一个,贝茜和她的同伴们有时不得不路过一些她们讨厌的可怕的树.奶牛们已经厌倦了被迫走某一条路,所以她们想建一些新路,使每一对草场之间都会至少有两条相互分离的路径,这样她们就有多一些选择. 每对草场之间已经有至少一条路径.给出所有R(F-1≤R≤10000)条双向路的描述,每条路连接了两个不同的草场,请计算最少的新建道路的数量, 路径由若干道路首尾相连而成.两条路径相互分离,是指两条路径没有一条重合的道路.但是,两条分离的路径上可以有一些相同的草场.

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

传送门 解题思路 刚开始是找的桥,后来发现这样不对,因为一条链就可以被卡.后来想到应该缩点后找到度数为1 的点然后两两配对. #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<set> using namespace std; const int MAXN = 5005; const int MAXM = 10005; inline i

[USACO06JAN]冗余路径Redundant Paths 无向图tarjan缩点

如题,缩完点后数一下有几个入度为1的scc,+1再/2即可. 教训:加一个cntf处理重边!否则重边会被认为是同一条. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 8 struct stack{ 9 vector<int> v;

冗余路径 Redundant Paths e-DCC缩点

冗余路径 Redundant Paths 题目传送 sol: 如果两点间存在至少两条不重复的路径,这说明他们两点在同一个边双连通分量(不存在割边). 那么可以进行e-DCC的缩点,得到一棵树. 对于这棵树广泛意义上的叶子节点(度数为1)而言,都还至少需要一条边连向他. 那么可以贪心的一次连两个叶子节点,答案显然就是\(cnt+1>>1\). #include<bits/stdc++.h> #define IL inline #define RG register #define D

luogu题解 P2860[USACO冗余路径Redundant Paths] 缩点+桥

题目链接 https://www.luogu.org/problemnew/show/P2860 https://www.lydsy.com/JudgeOnline/problem.php?id=1718 分析 首先这题目的意思就是让任意两点之间至少有两条没有重复道路的路径,很显然,如果这个图不存在桥,就一定满足上述条件. 于是我们就是要求使这个图不存在桥需要连接的最小边数 如果把桥从图中去掉,很显然剩余的联通块中任意两点之间至少有两条没有重复道路的路径(当然也可能不是联通块而是孤立的点),对答

冗余路径Redundant Paths

题意翻译 题目描述 在Byteotia有n个城镇. 一些城镇之间由无向边连接. 在城镇外没有十字路口,尽管可能有桥,隧道或者高架公路(反正不考虑这些).每两个城镇之间至多只有一条直接连接的道路.人们可以从任意一个城镇直接或间接到达另一个城镇. 每个城镇都有一个公民,他们被孤独所困扰.事实证明,每个公民都想拜访其他所有公民一次(在主人所在的城镇).所以,一共会有n*(n-1)次拜访. 不幸的是,一个程序员总罢工正在进行中,那些程序员迫切要求购买某个软件. 作为抗议行动,程序员们计划封锁一些城镇,阻

BZOJ 1718: [Usaco2006 Jan] Redundant Paths 分离的路径( tarjan )

tarjan求边双连通分量, 然后就是一棵树了, 可以各种乱搞... ------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 5009; struct edge { int to; b

1718: [Usaco2006 Jan] Redundant Paths 分离的路径

1718: [Usaco2006 Jan] Redundant Paths 分离的路径 Time Limit: 5 Sec  Memory Limit: 64 MB链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1718 Description In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1..F) to an