試題編號(hào): | 201509-4 |
試題名稱: | 高速公路 |
時(shí)間限制: | 1.0s |
內(nèi)存限制: | 256.0MB |
問題描述: | 問題描述 某國(guó)有n個(gè)城市,為了使得城市間的交通更便利,該國(guó)國(guó)王打算在城市之間修一些高速公路,由于經(jīng)費(fèi)限制,國(guó)王打算第一階段先在部分城市之間修一些單向的高速公路。 現(xiàn)在,大臣們幫國(guó)王擬了一個(gè)修高速公路的計(jì)劃。看了計(jì)劃后,國(guó)王發(fā)現(xiàn),有些城市之間可以通過高速公路直接(不經(jīng)過其他城市)或間接(經(jīng)過一個(gè)或多個(gè)其他城市)到達(dá),而有的卻不能。如果城市A可以通過高速公路到達(dá)城市B,而且城市B也可以通過高速公路到達(dá)城市A,則這兩個(gè)城市被稱為便利城市對(duì)。 國(guó)王想知道,在大臣們給他的計(jì)劃中,有多少個(gè)便利城市對(duì)。輸入格式 輸入的第一行包含兩個(gè)整數(shù)n, m,分別表示城市和單向高速公路的數(shù)量。 接下來m行,每行兩個(gè)整數(shù)a, b,表示城市a有一條單向的高速公路連向城市b。輸出格式 輸出一行,包含一個(gè)整數(shù),表示便利城市對(duì)的數(shù)量。樣例輸入5 51 22 33 44 23 5樣例輸出3樣例說明![]() |
問題鏈接:CCF201509試題。
問題描述:(參見上文)。
問題分析:這是一個(gè)強(qiáng)聯(lián)通圖的問題,用Tarjan算法來解決。另外一個(gè)算法是kosaraju算法,也用于解決強(qiáng)聯(lián)通圖問題。
程序說明:本程序采用Tarjan算法。主函數(shù)main()中,創(chuàng)建圖對(duì)象是參數(shù)本應(yīng)該用n,但是提交后出現(xiàn)了運(yùn)行錯(cuò)誤,所有改成n+1。程序通過使用Tarjan算法類(參見以下鏈接)來實(shí)現(xiàn),做了簡(jiǎn)單修改,使用變量ans來存儲(chǔ)結(jié)果,其中增加了中間變量count。
求得強(qiáng)聯(lián)通子圖后,對(duì)于每一個(gè)強(qiáng)聯(lián)通子圖如果有k個(gè)結(jié)點(diǎn),若k>1則強(qiáng)聯(lián)通對(duì)結(jié)點(diǎn)的數(shù)量為k*(k-1)/2,若k=1則為0。
相關(guān)鏈接:Tarjan算法查找強(qiáng)聯(lián)通組件。
提交后得100分的C++語言程序如下:
/* CCF201509-4 高速公路 */#include <iostream>#include <list>#include <stack>using namespace std;const int NIL = -1;int ans = 0;// A class that rePResents an directed graphclass Graph{ int V; // No. of vertices list<int> *adj; // A dynamic array of adjacency lists // A Recursive DFS based function used by SCC() void SCCUtil(int u, int disc[], int low[], stack<int> *st, bool stackMember[]);public: Graph(int V); // Constructor void addEdge(int v, int w); // function to add an edge to graph void SCC(); // prints strongly connected components};Graph::Graph(int V){ this->V = V; adj = new list<int>[V];}void Graph::addEdge(int v, int w){ adj[v].push_back(w);}// A recursive function that finds and prints strongly connected// components using DFS traversal// u --> The vertex to be visited next// disc[] --> Stores discovery times of visited vertices// low[] -- >> earliest visited vertex (the vertex with minimum// discovery time) that can be reached from subtree// rooted with current vertex// *st -- >> To store all the connected ancestors (could be part// of SCC)// stackMember[] --> bit/index array for faster check whether// a node is in stackvoid Graph::SCCUtil(int u, int disc[], int low[], stack<int> *st, bool stackMember[]){ // A static variable is used for simplicity, we can avoid use // of static variable by passing a pointer. static int time = 0; // Initialize discovery time and low value disc[u] = low[u] = ++time; st->push(u); stackMember[u] = true; // Go through all vertices adjacent to this list<int>::iterator i; for (i = adj[u].begin(); i != adj[u].end(); ++i) { int v = *i; // v is current adjacent of 'u' // If v is not visited yet, then recur for it if (disc[v] == -1) { SCCUtil(v, disc, low, st, stackMember); // Check if the subtree rooted with 'v' has a // connection to one of the ancestors of 'u' // Case 1 (per above discussion on Disc and Low value) low[u] = min(low[u], low[v]); } // Update low value of 'u' only of 'v' is still in stack // (i.e. it's a back edge, not cross edge). // Case 2 (per above discussion on Disc and Low value) else if (stackMember[v] == true) low[u] = min(low[u], disc[v]); } // head node found, pop the stack and print an SCC int w = 0; // To store stack extracted vertices int count = 0; if (low[u] == disc[u]) { while (st->top() != u) { w = (int) st->top();// cout << w << " "; count++; stackMember[w] = false; st->pop(); } w = (int) st->top();// cout << w << "/n"; count++; stackMember[w] = false; st->pop(); } if(count > 1) ans += count * (count -1) / 2;}// The function to do DFS traversal. It uses SCCUtil()void Graph::SCC(){ int *disc = new int[V]; int *low = new int[V]; bool *stackMember = new bool[V]; stack<int> *st = new stack<int>(); // Initialize disc and low, and stackMember arrays for (int i = 0; i < V; i++) { disc[i] = NIL; low[i] = NIL; stackMember[i] = false; } // Call the recursive helper function to find strongly // connected components in DFS tree with vertex 'i' for (int i = 0; i < V; i++) if (disc[i] == NIL) SCCUtil(i, disc, low, st, stackMember);}int main(){ int n, m, src, dest; cin >> n >> m; Graph g(n+1); for(int i=1; i<=m; i++) { cin >> src >> dest; g.addEdge(src, dest); } g.SCC(); cout << ans << endl; return 0;}
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注