边双连通分量

来源:互联网 发布:影像拼接 软件 编辑:程序博客网 时间:2024/04/30 05:13

关于桥与双连通分支的定义及求法void大神给出了很详尽的介绍图的割点、桥与双连通分支


总结几条做题过程中发现的关于边双连通分量的性质:

1.将图中每个边连通分量缩为一个点后,只连端点不位于同一连通分量中的边,则将图转换成了一棵树,且树中的边都是父子边。

2.在对图进行搜索时,图中的边分为父子边和返祖边(交叉边),则一个具有n个点的边连通分量中有且仅有n-1条父子边,且可由着n-1以条边连成一棵树,剩余的边都是返祖边。

关于双连通图的构造和判定等基本问题void文章里有详细介绍,我的《连通性问题》中也有写。

poj3694 Network

题意:讯问在现有网络中添加一条边<a,b>后图中有多少条桥。

显然,若ab位于同一连通分支时不会影响桥,因此变为缩点后的树中两点之间路径上有多少条桥,由于在求双连通时记录了每个点的深度,因此不必单独求lca只需延父节点向上走,知道两个点的某个祖先相同,在寻找lca的过程中可以顺便提及出有多少条桥。

int LCA(int a, int b) {if(dfn[a]<dfn[b]){int temp=a;a=b;b=temp;}while(dfn[a]>dfn[b]){        if(bridge[a]){            sum--;            bridge[a]=false;        }        a=fa[a];    }    while(a!=b){        if(bridge[a]){sum--;bridge[a]=false;}        if(bridge[b]){sum--;bridge[b]=false;}        a=fa[a];b=fa[b];    }return sum;}
poj1515 Street Direction / poj1438 One-Way Traffic

题意:有m条无向边确保n个点两两可达,要求将尽可能多的双向边变为单向边,使得任意两点之间仍然可达,并给出一组方案。

解法:对于无向图的桥,肯定要保持双向,对于双连通分量分量内的点,只要确保构成果敢个环就可以,一开始想到了dfs求环路,后来想到了染色,其实构成环路的边就是搜索时的父子边和返祖边,按照原本的方向构造就可以。 

1438是1515的延伸,有些路已经是单向的了。其实很简单,只要在加边的时候加单向边,就相当于给一条无向边规定了性质,然后做相同的处理即可

public class Main{int maxn=1010,maxm=10010;class BCC {class node {int ne, be;int type;node(int be, int ne) {this.ne = ne;this.be = be;}}node buf[] = new node[maxm];int E[] = new int[maxn], len, n;int dfn[] = new int[maxn], low[] = new int[maxn], cnt;int vis[] = new int[maxn], fa[] = new int[maxn], sum;boolean bridge[] = new boolean[maxm];void init(int n) {this.n = n;Arrays.fill(E, -1);len = 0;}void add(int a, int b) {buf[len] = new node(b, E[a]);E[a] = len++;buf[len] = new node(a, E[b]);E[b] = len++;}void dfs(int a) {vis[a] = 1;dfn[a] = low[a] = ++cnt;for (int i = E[a]; i != -1; i = buf[i].ne) {int b = buf[i].be;if (vis[b] == 1 && b != fa[a]){buf[i].type=1;//返祖边low[a] = Math.min(low[a], dfn[b]);}if (vis[b] == 0) {buf[i].type=2;//父子边fa[b] = a;dfs(b);low[a] = Math.min(low[b], low[a]);if (low[b] > dfn[a]) {buf[i].type=3;////System.out.println(a+" bb "+b+" "+i);}}}vis[a] = 2;}void solve() {Arrays.fill(dfn, 0);Arrays.fill(low, 0);Arrays.fill(bridge, false);Arrays.fill(vis, 0);cnt = sum = 0;for (int i = 1; i <= n; i++)fa[i] = i;dfs(1);}void go(){for(int i=1;i<=n;i++)for(int j=E[i];j!=-1;j=buf[j].ne){//System.out.println(i+" "+j);if(buf[j].type==0)continue;int b=buf[j].be;                    System.out.println(i+" "+b);if(buf[j].type==3)System.out.println(b+" "+i);}}}StreamTokenizer in = new StreamTokenizer(new BufferedReader(            new InputStreamReader(System.in)));     int nextInt() throws IOException {        in.nextToken();        return (int) in.nval;    }    BCC bcc=new BCC();    void run() throws IOException    {    int cas=0;    while(++cas>0){    int n=nextInt();    int m=nextInt();    if(n==0)    break;    System.out.println(cas+"\n");    bcc.init(n);    for(int i=1;i<=m;i++)    bcc.add(nextInt(), nextInt());    bcc.solve();    bcc.go();    System.out.println("#");    }    }public static void main(String[] args) throws IOException {new Main().run();}}

原创粉丝点击