bzoj1718[Usaco2006 Jan] Redundant Paths 分离的路径 边双连通分量
2017-06-17 09:50
429 查看
这题想到一半了,最后缩点以后的统计答案挂了= =。。。
题意就不说了,问你加入多少条边能使得所有边都是一个边双。
n有点小了,怀疑有n^2水法。
求出边双以后缩点比较显然,然后我就有点蒙逼了,不知道怎么统计答案。。
想了dp和二分等奇怪姿势,然而好像都没用。
后来看了一波题解才发现是结论= =一棵树,要让他任意两点之间有超过1条路径相连,答案是(叶子节点个数+1)/2。
为啥呢?因为,一棵树,我们一开始不加边,他们之间的路径肯定是向上走然后相交,那么第二条路径,我们要加的边尽量少,则重复的边尽量少,所以我们在不同子树之间的叶子节点之间两两配对就好了,当然如果只有一个叶子节点就两个都连过去。。
注意最后统计叶子节点的时候,只有是桥的边才是树上的边。
题意就不说了,问你加入多少条边能使得所有边都是一个边双。
n有点小了,怀疑有n^2水法。
求出边双以后缩点比较显然,然后我就有点蒙逼了,不知道怎么统计答案。。
想了dp和二分等奇怪姿势,然而好像都没用。
后来看了一波题解才发现是结论= =一棵树,要让他任意两点之间有超过1条路径相连,答案是(叶子节点个数+1)/2。
为啥呢?因为,一棵树,我们一开始不加边,他们之间的路径肯定是向上走然后相交,那么第二条路径,我们要加的边尽量少,则重复的边尽量少,所以我们在不同子树之间的叶子节点之间两两配对就好了,当然如果只有一个叶子节点就两个都连过去。。
注意最后统计叶子节点的时候,只有是桥的边才是树上的边。
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cmath> #define fo(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) using namespace std; int n, m; const int N = 1e5 + 5; int read() { int x = 0, f = 1; char ch = getchar(); while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x*f; } int dfn , low ,dep ; bool vis ,isc ,isb ; int head , go , nxt ; int tot=1, cnt, tim; inline void add(int x, int y) { go[++tot] = y; nxt[tot] = head[x]; head[x] = tot; } inline void dfs(int x, int pre) { dfn[x]=low[x]=++tim; for (int i = head[x]; i; i = nxt[i]) { int v = go[i]; if ((i^1)!=pre) if (!dfn[v]) dfs(v, i), low[x] = min(low[x], low[v]); else low[x] = min(low[x], dfn[v]); } if (pre&&low[x] == dfn[x]) isb[pre] = isb[pre ^ 1] = 1; } int bel ; inline void rebuild(int x, int num) { bel[x] = num; for (int i = head[x]; i; i = nxt[i]) { int v = go[i]; if (!bel[v] && !isb[i])rebuild(v, num); } } int main() { n = read(), m = read(); fo(i, 1, m) { int x=read(), y=read(); add(x, y); add(y, x); } int blocksum = 0; fo(i, 1, n)if (!dfn[i])dfs(1,0); fo(i, 1, n)if (!bel[i])rebuild(i, ++blocksum); for (int i = 2; i <= tot; i += 2)if (isb[i])dep[bel[go[i]]]++, dep[bel[go[i ^ 1]]]++; int ans = 0; fo(i, 1, blocksum)if (dep[i] == 1)ans++; printf("%d\n", (ans + 1) >> 1); }
相关文章推荐
- bzoj 1718: [Usaco2006 Jan] Redundant Paths 分离的路径
- 【BZOJ】1718: [Usaco2006 Jan] Redundant Paths 分离的路径
- bzoj 1718: [Usaco2006 Jan] Redundant Paths 分离的路径
- BZOJ 1718: [Usaco2006 Jan] Redundant Paths 分离的路径
- BZOJ 1718 [Usaco2006 Jan] Redundant Paths 分离的路径 双联通分量
- BZOJ 1718: [Usaco2006 Jan] Redundant Paths 分离的路径( tarjan )
- BZOJ1718 [Usaco2006 Jan] Redundant Paths 分离的路径
- BZOJ1718: [Usaco2006 Jan] Redundant Paths 分离的路径
- bzoj 1718: [Usaco2006 Jan] Redundant Paths 分离的路径【tarjan】
- BZOJ1718 [Usaco2006 Jan] Redundant Paths 分离的路径
- BZOJ 1654: [Usaco2006 Jan]The Cow Prom 奶牛舞会
- |BZOJ 1654|强连通分量|[Usaco2006 Jan]The Cow Prom 奶牛舞会
- BZOJ P1656[Usaco2006 Jan] The Grove 树木
- 【强连通分量】Bzoj1654 [Usaco2006 Jan]The Cow Prom 奶牛舞会
- bzoj:1654 [Usaco2006 Jan]The Cow Prom 奶牛舞会
- bzoj1656: [Usaco2006 Jan] The Grove 树木 (bfs+新姿势)
- bzoj 1720: [Usaco2006 Jan]Corral the Cows 奶牛围栏 二分
- bzoj 1656: [Usaco2006 Jan] The Grove 树木 (bfs+技巧)
- bzoj1654: [Usaco2006 Jan]The Cow Prom 奶牛舞会
- [BZOJ1654] [Usaco2006 Jan]The Cow Prom 奶牛舞会