/* digraph.h : 有向グラフアルゴリズム関数定義部 K. Shiota 2005.6.13- */ /*********** 有向グラフ操作関数定義部 **********/ /* 有向グラフ g の弧 uv を除去した有向グラフを返す */ /* 多重弧の場合は1本のみ除去 */ Graph RemoveArc(Graph g, int u, int v) { Graph h=g; h.adj[u][v]--; return h; } /* 有向グラフ g に弧 uv を付加した有向グラフを返す */ Graph AddArc(Graph g, int u, int v) { Graph h=g; h.adj[u][v]++; return h; } /* 有向グラフ g の弧 uv を縮約した有向グラフを返す */ Graph ContractArc(Graph g, int u, int v) { Graph h=g; int i,j,t; for(i=0;i255){ printf("最大重みは 255 までにしてください。\n"); exit(1); } g.ord=n; for(i=0;i0 && !ListMemberQ(i,cl)){ // 現在の探索点の隣接点で未探索の点を探し見つかれば p->mem[i]=c; // 親を登録 t.adj[c][i]=1; // 探索木の弧を登録 cl.mem[cl.len++]=i; // 探索済みリストに登録 c=i; // 現在点を i に進める b=0; // バックトラックは不要 break; } } if(b){ // バックトラックが必要なとき // 現在点が r ならこれ以上の探索は不可能 // そうでなければ探索点の親へ戻る if(c==r) f=1; else c=p->mem[c]; } }while(cl.len!=g.ord && !f); // 全ての点を探索し終わったか、探索続行不可能で終了 return t; } /* 有向グラフ g を根 r から広さ優先探索する */ /* p : 親 ( parent ) を登録するリスト */ /* 返り値は広さ優先探索木 */ Graph WFSDirectedTree(Graph g, int r, List *p) { Graph t; // 最終的に広さ優先探索木を格納して返り値にする List ll; // 各 node のレベルを登録するリスト int c; // 現在の探索点 ( current node ) int f; // 連結成分を探索し終わったか否か ( finish ) int l=0; // 現在のレベル int i,j; t=EmptyGraph(g.ord); // 木の初期化 *p=ListInitialize(g.ord,-1); // 親が居ないと -1 ll=ListInitialize(g.ord,-1); // r 以外の点のレベルの初期値は -1 ll.mem[r]=l; do{ f=1; for(c=0;c0 && ll.mem[i]==-1){ // 現在の探索点の隣接点で未探索の点を探し見つかれば p->mem[i]=c; // 親を登録 t.adj[c][i]=1; // 探索木の弧を登録 ll.mem[i]=l+1; // レベルを l+1 に設定 f=0; // 探索続行可能 } } } } l++; // レベルを +1 }while(ListMemberQ(-1,ll) && !f); // 全ての点を探索し終わったか、探索続行不可能で終了 return t; } /* 有向グラフ g から多重弧とループを取り去った有向グラフを返す */ Graph SimplifiedDiGraph(Graph g) { Graph h=g; int i,j; for(i=0;i0) h.adj[i][j]=1; } return h; } /* 有向グラフ g を単純無向化したグラフを返す */ Graph SimplifiedUndirectedGraph(Graph g) { Graph h=g; int i,j; for(i=0;i0 || g.adj[j][i]>0){ h.adj[i][j]=1; h.adj[j][i]=1; } } } return h; } /* 有向グラフ g が弱連結か否か判定する */ int WeakConnectedQ(Graph g) { return ConnectedQ(SimplifiedUndirectedGraph(g)); } /* 頂点 u の入次数 */ int InDegree(Graph g, int u) { int i,d=0; for(i=0;i0){ t=-1; // 橋による隣接点登録用変数 b=0; // 橋以外の隣接点があれば 1 for(i=0;i0){ if(c==i){ // ループは先に回ろう h=RemoveArc(h,c,i); r--; ec[k++]=c; // サーキットに c を登録 b=1; // 橋以外の隣接点があった break; } // ci が橋でなければ i へ進む if(!DirectedBridgeQ(h,c,i)){ h=RemoveArc(h,c,i); r--; ec[k++]=i; // サーキットに i を登録 c=i; // 現在位置を i に更新 b=1; // 橋以外の隣接点があった break; } else{ if(t==-1) t=i; // ci が橋のときは t=i を仮登録 } } } if(b==0){ h=RemoveArc(h,c,t); r--; ec[k++]=t; // サーキットに t を登録 c=t; // 現在位置を t に更新 } } return m; }