UVa 610 Street Directions
Uva 610 Street Directions
http://uva.onlinejudge.org/external/6/610.html
問題概要
無向グラフがあたえられる。
いくつかのエッジを有向辺に変更する。
変更後もすべて強連結なグラフでないといけない。
選ぶエッジを最大化したとき、得られる有向グラフを構成するエッジを答えよ。
解法
橋をみつけ、橋だけ無向辺のままにする。
分割した橋の持たないグラフにエッジをDFSで割り振る。
橋を含まないグラフでDFS木を作ると、
根以外のノードsは必ずsの祖先への後退辺をs自身、あるいは、sの子孫が持つ。
よって、
- 全ての子ノードは根ノードへの道を持つ
- 根ノードは子ノードへの道を持つ
ので、木を構成している辺と後退辺で構成すると、強連結なグラフになる。
ソース
#include<iostream> #include<algorithm> #include<vector> #define REP(i,b,n) for(int i=b;i<(int)n;i++) #define rep(i,n) REP(i,0,n) #define FOR(it,o) for(__typeof((o).begin()) it=(o).begin(); it!=(o).end(); ++it) using namespace std; const int V = 1000; int n; bool edge[V][V], preUsed[V][V], used[V][V]; int preNum[V], low[V], rootNode, defultID[V]; vector<pair<int, int> > Edge; int dfs(int nowNode, int &nowNum){ low[nowNode] = preNum[nowNode] = nowNum; defultID[nowNum] = nowNode; nowNum++; rep(i, n){ if(!edge[nowNode][i])continue; if(preNum[i] >= 0){ if(preUsed[i][nowNode])continue; low[nowNode] = min(low[nowNode], preNum[i]); if(used[nowNode][i])continue; Edge.push_back(make_pair(nowNode, i)); used[nowNode][i] = used[i][nowNode] = true; } else{ preUsed[nowNode][i] = true; Edge.push_back(make_pair(nowNode, i)); used[nowNode][i] = used[i][nowNode] = true; low[nowNode] = min(dfs(i, nowNum), low[nowNode]); } } return low[nowNode]; } void getBridge(){ rep(i, n){ rep(j, n){ if(!preUsed[i][j])continue; if(low[j] == preNum[j]){ Edge.push_back(make_pair(defultID[max(preNum[i], preNum[j])], defultID[min(preNum[i], preNum[j])])); } } } } void setGraph(){ rootNode = 0; rep(i, n){ preNum[i] = -1; rep(j, n){ used[i][j] = false; preUsed[i][j] = false; } } int id= 0; dfs(rootNode, id); } int main(){ int m; int tc = 0; while(cin >> n >> m){ tc++; if(n == 0&& m == 0)break; cout << tc << endl << endl; rep(i, n)rep(j, n)edge[i][j] = false; rep(i, m){ int from, to; cin >> from >> to; from--;to--; edge[from][to] = edge[to][from] = true; } Edge.clear(); setGraph(); getBridge(); FOR(it, Edge){ cout << it->first + 1 <<' ' << it->second +1<< endl; } cout << "#" << endl; } return 0; }