poj3177 Redundant Paths
2015-11-13 10:05
344 查看
思路:给出一张无向连通图,问至少需要添加几天边可以使得图中任何两个点有至少两天不同路径(边不重合),等价于至少添加几条边可以使得图为双连通分量-边连通。
显然已经处于某连通分量中的点之间必然存在两条不同路径,所以可以等效的把这个连通分量看成一个点来对待,这样就是缩点了,然后得到一棵树,此时推一下就知道还需要的边数=(叶子节点数 + 1)/ 2。
显然已经处于某连通分量中的点之间必然存在两条不同路径,所以可以等效的把这个连通分量看成一个点来对待,这样就是缩点了,然后得到一棵树,此时推一下就知道还需要的边数=(叶子节点数 + 1)/ 2。
// #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <algorithm> #include <iomanip> #include <sstream> #include <string> #include <stack> #include <queue> #include <deque> #include <vector> #include <map> #include <set> #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> #include <limits.h> // #define DEBUG #ifdef DEBUG #define debug(...) printf( __VA_ARGS__ ) #else #define debug(...) #endif #define MEM(x,y) memset(x, y,sizeof x) using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int maxn = 5010; const int maxm = 20010; int head[maxn], nxt[maxm], pnt[maxm]; bool go[maxm]; int cnt; void addedge(int u,int v){ pnt[cnt] = v;nxt[cnt] = head[u];go[cnt] = false;head[u] = cnt++; pnt[cnt] = u;nxt[cnt] = head[v];go[cnt] = false;head[v] = cnt++; } int dfn[maxn], low[maxn], id[maxn]; bool vis[maxn]; int t; stack<int> st; int num; void Tarjan(int u,int fa){ // cout << "u = " << u << endl; dfn[u] = low[u] = t++; st.push(u); vis[u] = true; bool flag = true; for (int i = head[u];i != -1;i = nxt[i]){ if (go[i]) continue; go[i] = go[i ^ 1] = true; int v = pnt[i]; // cout << "v = " << v << endl; if (dfn[v] == -1){ // go[i] = go[i^1] = true; // printf("(%d, %d)\n",u, v); Tarjan(v, u); low[u] = min(low[v], low[u]); } else if (low[u] > dfn[v] && vis[v]){ low[u] = dfn[v]; } } // printf("low[%d] = %d,dfn[%d] = %d\n",u, low[u], u, dfn[u]); if (low[u] == dfn[u]){ // printf("***(%d)***\n", u); while(true){ int v = st.top(); st.pop(); vis[v] = false; id[v] = num; if (v == u) break; } num++; } } int in[maxn]; void Read(){ int n, m; scanf("%d%d",&n,&m); cnt = num = t = 0; MEM(head, -1); MEM(dfn, -1); MEM(low, -1); MEM(vis, false); while(!st.empty()) st.pop(); for (int i = 1, a ,b;i <= m;++i){ scanf("%d%d",&a, &b); addedge(a, b); // addedge(b, a); } for (int i = 1;i <= n;++i) if (dfn[i] == -1) Tarjan(i, -1); // cout << "num = " << num << endl; // for (int i = 1;i <= n;++i) // cout << id[i] << ' '; // cout << endl; for (int i = 1;i <= n;i++){ for (int j = head[i];j != -1;j = nxt[j]){ int u = id[i]; int v = id[pnt[j]]; if (u != v) in[u]++,in[v]++; } } cnt = 0; for (int i = 0;i < num;++i) if (in[i] == 2) cnt++; printf("%d\n",(cnt + 1) / 2); } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); Read(); return 0; }
相关文章推荐
- C++ Builder/Delphi中的Form控件
- md5加密
- ExtAspNet2.1.0版本
- 前端系统学习快速进阶教程全攻略
- javascript:void(0)是什么意思及href=#与href=javascriptvoid(0)的区别
- java获得上一月
- IOS8企业版无法通过itms-services覆盖安装,没反应
- CentOS x64上Matlab R2015b的镜像安装方法与卸载
- JSP引用JS文件中文乱码问题
- and,or,order by
- 和尚挖井故事给程序员的启示
- 仿真开发过程之需求
- 《从零开始学Swift》学习笔记(Day 35)——会使用下标吗?
- AVD模拟器无法上网解决方法
- SQL定义
- PopupWindow学习笔记
- Win10 TH2正式版微软官方中文简体ISO镜像下载 附介质创建工具下载
- POJ 3189——Steady Cow Assignment——————【多重匹配、二分枚举区间长度】
- 关于为什么window.frames[0].src不能获取src
- 修改双系统(Linux系统和Windows系统)的启动顺序和等待时间