【专题】图的连通性问题---无向图的点连通性的求解及应用
2012-05-23 22:31
302 查看
1.求割点:
(1).朴素的方法:n^3
(2).Tarjan求割点:n^2
顶点u是割点的充要条件:
1.如果顶点u是深度优先搜索生成树的根,则u至少有两个子女.
2.如果u不是生成树的根,则它至少有一个子女w,从w出发,不可能通过w、w的子孙,以及一条回边组成的路径到达u的祖先.
(low[w]>=dfn[u]).
去掉割点,将原来的连通图分成了几个连通分量?
1.如果割点u是根结点,则有几个子女,就分成了几个连通分量.
2.如果割点u不是根结点,则有d个子女w,使得low[w]>=dfn[u],则去掉该结点,分成了d+1个连通分量。
下面是一段求割点的代码:
View Code
Stoer-Wagner算法:O(n^3),见博客L:
/article/6193857.html
(1).朴素的方法:n^3
(2).Tarjan求割点:n^2
顶点u是割点的充要条件:
1.如果顶点u是深度优先搜索生成树的根,则u至少有两个子女.
2.如果u不是生成树的根,则它至少有一个子女w,从w出发,不可能通过w、w的子孙,以及一条回边组成的路径到达u的祖先.
(low[w]>=dfn[u]).
去掉割点,将原来的连通图分成了几个连通分量?
1.如果割点u是根结点,则有几个子女,就分成了几个连通分量.
2.如果割点u不是根结点,则有d个子女w,使得low[w]>=dfn[u],则去掉该结点,分成了d+1个连通分量。
下面是一段求割点的代码:
View Code
/*Source Code Problem: 1966 User: HEU_daoguang Memory: 1056K Time: 16MS Language: G++ Result: Accepted Source Code*/ #include <iostream> #include <stdio.h> #include <string.h> using namespace std; #define V 300 #define E 30000 #define inf 0xffff int map[V][2]; int flag[V][V]; struct Edge { int u,v,c,next; }edge[E]; int n,m,cnt; int dist[V]; int head[V]; int que[V]; int sta[V]; int s,t; void init(){ cnt=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int c){ edge[cnt].u=u;edge[cnt].v=v;edge[cnt].c=c; edge[cnt].next=head[u];head[u]=cnt++; edge[cnt].u=v;edge[cnt].v=u;edge[cnt].c=0; edge[cnt].next=head[v];head[v]=cnt++; } int dinic(int s,int t){ int ans=0; while(true){ int left,right,u,v; memset(dist,-1,sizeof(dist)); left=right=0; que[right++]=s; dist[s]=0; while(left<right){ u=que[left++]; for(int k=head[u];k!=-1;k=edge[k].next){ u=edge[k].u; v=edge[k].v; if(edge[k].c > 0 && dist[v]==-1){ dist[v]=dist[u]+1; que[right++]=v; if(v==t){ left=right; break; } } } } if(dist[t]==-1) break; int top=0; int now=s; while(true){ if(now!=t){ int k; for(k=head[now];k!=-1;k=edge[k].next){ if(edge[k].c>0 && dist[edge[k].v]==dist[edge[k].u]+1) break; } if(k!=-1){ sta[top++]=k; now=edge[k].v; } else{ if(top==0) break; dist[edge[sta[--top]].v]=-1; now=edge[sta[top]].u; } } else{ int flow=inf,ebreak; for(int i=0;i<top;i++){ if(flow>edge[sta[i]].c){ flow=edge[sta[i]].c; ebreak=i; } } ans+=flow; for(int i=0;i<top;i++){ edge[sta[i]].c-=flow; edge[sta[i]^1].c+=flow; } now=edge[sta[ebreak]].u; top=ebreak; } } } return ans; } void build(int x,int y,int ver,int n,int m){ init(); for(int i=1;i<=n;i++){ addedge(i,i+n,1); } for(int i=0;i<m;i++){ addedge(map[i][0]+n,map[i][1],inf); addedge(map[i][1]+n,map[i][0],inf); } addedge(x,x+n,inf); addedge(y,y+n,inf); } int main() { //freopen("in.txt","r",stdin); while(scanf("%d%d",&n,&m)!=EOF){ int a,b; int ver=n*2+1; memset(map,0,sizeof(map)); memset(flag,0,sizeof(flag)); for(int i=0;i<m;i++){ scanf(" (%d,%d)",&a,&b); a++,b++; map[i][0]=a,map[i][1]=b; flag[a][b]=1; } if(m==0){ if(n==1) printf("1\n"); else printf("0\n"); continue; } int pre,ans=inf,sign=0; for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ if(!flag[i][j]){ sign=1; build(i,j,ver,n,m); ans=min(ans,dinic(i,j+n)); } } } if(sign){ printf("%d\n",ans); } else{ printf("%d\n",n); } } return 0; }
Stoer-Wagner算法:O(n^3),见博客L:
/article/6193857.html
相关文章推荐
- 【专题】图的连通性问题---有向图的强连通性的求解及应用
- 第十一周-项目4-5-应用图的深度优先遍历思路求解问题
- 栈的应用——迷宫求解问题
- 图的点着色、区间着色问题及其应用(基于贪心思想的DFS回溯法求点着色问题和区间着色算法求解任务调度问题)
- 数据结构应用案例——栈结构用于8皇后问题的回溯求解
- 队列应用1:求解报数问题
- [双连通+割点+桥]无向图连通性问题专题
- 数据结构的应用——使用栈和递归实现Hanoi问题求解
- 迷宫求解问题-递归(栈的应用)
- 迷宫问题的求解方式:应用深度优先和广度优先的搜索
- 第十二周 项目四 应用图的深度优先遍历思路求解问题
- 队列应用2:求解迷宫问题,最短路径
- 第十一周——项目四(2)—应用图的广度优先遍历思路求解问题
- 应用图的深度优先遍历思路求解问题1
- 第十二周--项目4应用图的深度优先遍历思路求解问题 (5)
- 数据结构例程——应用图的深度优先遍历思路求解问题
- 动态规划5:求解最多航线问题(应用了最长子序列知识)
- 【JAVA编码专题】 JAVA字符编码系列三:Java应用中的编码问题 分类: B1_JAVA 2015-02-10 21:05 135人阅读 评论(0) 收藏
- 数据结构例程——应用图的广度优先遍历思路求解问题
- 应用图的深度优先遍历思路求解问题2