poj3694 Network
来源:互联网 发布:windows远程ubuntu 编辑:程序博客网 时间:2024/04/26 01:24
链接:http://poj.org/problem?id=3694
题意:有一个网络。问每添加一条边,整个新图中有多少条桥?
#include<cstdio>#include<cstring>#define MAXN 100005using namespace std;struct Edge{ int to; int next;}edge[MAXN*4];int n,m;int ans,cnt,index;int head[MAXN],dfn[MAXN],low[MAXN],farther[MAXN],set[MAXN];//father[u]为当前u节点的父节点//set数组用于并查集中节点的划分void init(){index=ans=cnt=0;for(int i=1;i<=n;i++){set[i]=i;dfn[i]=0;head[i]=-1;farther[i]=0;}}void add(int u,int v){edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].to=u; edge[cnt].next=head[v]; head[v]=cnt++;}int find(int x){if(x!=set[x])set[x]=find(set[x]);return set[x];}int merge(int a,int b){int x=find(a); int y=find(b); if(x==y)return 0;else set[y]=x; return 1;}void tarjan(int u,int fa){ int i,v; dfn[u]=low[u]=++index; for(i=head[u];i!=-1;i=edge[i].next) { v=edge[i].to; if(v==fa)continue; if(!dfn[v]) { tarjan(v,u);farther[v]=u; //设置当前节点v的父节点为u if(low[u]>low[v]) low[u]=low[v]; if(dfn[u]<low[v]) //edge(u,v)为割边,ans++ ans++; elsemerge(u,v);//否则,属于一个连通分量,就合并,利用并查集缩点 } else if(low[u]>dfn[v]) low[u]=dfn[v]; }}void lca(int u,int v){while(u!=v){ while(dfn[u]>=dfn[v]&&u!=v)//点u的深度大于点v的深度 { if(merge(u,farther[u]))//如果u和father[u]不在同一个连通分量,则桥减一,因为势必形成环 ans--; u=farther[u]; //点u向上爬 } while(dfn[v]>=dfn[u]&&u!=v) { if(merge(v,farther[v])) ans--; v=farther[v]; }}}int main(){ int q,i,CASE=0; int a,b; while(scanf("%d%d",&n,&m)!=EOF) { if(!n&&!m)return 0;init(); for(i=0;i<m;i++) {scanf("%d%d",&a,&b); add(a,b); } scanf("%d",&q);tarjan(1,-1);printf("Case %d:\n",++CASE); for(i=0;i<q;i++) {scanf("%d%d",&a,&b);lca(a,b); printf("%d\n",ans); } }}
再附上网上的另一种方法,应该说方法一样的,只是一个是直接通过标记桥来判断。
思路:求双连通分量,利用并查集缩点,形成一棵树,树边肯定都是桥,然后每对点x,y,找原图中x,y点对应的新图中的点,如果不是一个点,则向上找它们的LCA,因为它们之间连了一条边,所以这些点到它们的LCA之间的边都不是割边了,找LCA时,先将两点上升到同一层次,然后一起再向上找父亲节点,其间遇到桥就把桥的标记删除,并且答案减1。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#define MAXN 100005#define MAXM 555555#define INF 1000000000using namespace std;struct Edge{ int v, next;}edge[MAXM];int low[MAXN], dfn[MAXN], index, vis[MAXN];int e, n, m, head[MAXN];int cnt, bridge[MAXN], father[MAXN];void init(){ e = 0, index = 0, cnt = 0; memset(vis, 0, sizeof(vis)); memset(dfn, 0, sizeof(dfn)); memset(bridge, 0, sizeof(bridge)); memset(head, -1, sizeof(head)); for(int i = 1; i <= n; i++) father[i] = i;}void insert(int x, int y){ edge[e].v = y; edge[e].next = head[x]; head[x] = e++;}void tarjan(int u){ vis[u] = 1; dfn[u] = low[u] = ++index; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; if(!vis[v]) { father[v] = u; tarjan(v); low[u] = min(low[u], low[v]); if(low[v] > dfn[u]) { cnt++; bridge[v] = 1; } } else if(vis[v] == 1 && v != father[u]) low[u] = min(low[u], dfn[v]); } vis[u] = 2;}void LCA(int u, int v){ while(dfn[u] > dfn[v]) { if(bridge[u]) cnt--, bridge[u] = 0; u = father[u]; } while(dfn[v] > dfn[u]) { if(bridge[v]) cnt--, bridge[v] = 0; v = father[v]; } while(u != v) { if(bridge[u]) cnt--, bridge[u] = 0; if(bridge[v]) cnt--, bridge[v] = 0; u = father[u]; v = father[v]; }}void ask(){ int q, u, v; scanf("%d", &q); while(q--) { scanf("%d%d", &u, &v); LCA(u, v); printf("%d\n", cnt); } printf("\n");}int main(){ int cas = 0; while(scanf("%d%d", &n, &m) != EOF) { if(n == 0 && m == 0) break; printf("Case %d:\n", ++cas); init(); int x, y; while(m--) { scanf("%d%d", &x, &y); insert(x, y); insert(y, x); } tarjan(1); ask(); } return 0;}
转自:http://blog.csdn.net/sdj222555/article/details/7211644
http://blog.csdn.net/zhengnanlee/article/details/22646327
0 0
- POJ3694--Network
- poj3694 Network
- POJ3694----Network
- poj3694 Network
- 【POJ3694】Network
- poj3694 Network
- poj3694 Network
- poj3694 Network Tarjan+树链剖分
- POJ3694 Network 割边+LCA
- poj3694 Network Tarjan(树链剖分)
- [POJ3694]Network(tarjan+链剖)
- POJ3694 Network 割边 LCA
- poj3694 Network 【图论-Tarjan-Lca】
- [双连通分量]poj3694 Network
- POJ3694-Network(Tarjan缩点+LCA)
- poj3694--Network(双连通缩点+lca)
- Network-POJ3694并查集+LCA
- POJ3694 Network(边双连通+LCA)
- asm--输入字符串,回车结束,逆序输出
- mysql innodb的row size限制
- 精通安卓性能优化-第一章(一)
- 操作对象数组 或数组 绑定后台序列化后的列表对象 将列表序列化成对象
- LINUX批量杀进程
- poj3694 Network
- 相机的颜色是这样来的
- 编译原理实验一 词法分析程序
- 使用mongodb实现前缀搜索提示功能
- Cxgrid获取选中行列,排序规则,当前正在编辑的单元格内的值
- 你可以不坚强
- SOJ 1001 Alphacode
- SQLite在.net的应用
- OpenCV2马拉松第10圈——直方图反向投影(back project)