/* *State: POJ3177 Accepted 340K 16MS C++ 1877B *题目大意: * 给出一个无向连通图,判断最少需要加多少条边,才能使得 * 任意两点之间至少有两条相互"边独立"的道路.注意,可能 * 含有重边. *解题思路: * 先缩点,之后形成一棵树,然后求(叶子节点数量+1)/ 2即可。 */
View Code
1 #include <iostream> 2 #include <vector> 3 #include <stack> 4 using namespace std; 5 6 const int MAXN = 5005; 7 const int MAXE = 10005; 8 9 vector<int> vec[MAXN]; 10 stack<int> S; 11 int dfn[MAXN], low[MAXN], step; 12 int id[MAXN], scc; 13 14 void init() 15 { 16 while(!S.empty()) 17 S.pop(); 18 19 step = 0; 20 scc = 1; 21 for(int i = 0; i < MAXN; i++) 22 { 23 id[i] = -1; 24 vec[i].clear(); 25 dfn[i] = low[i] = -1; 26 } 27 } 28 29 void addEdge(int u, int v) 30 { 31 vec[u].push_back(v); 32 vec[v].push_back(u); 33 } 34 35 void tarjan_scc(int n, int father) 36 { 37 dfn[n] = low[n] = ++step; 38 S.push(n); 39 int flag = 0; 40 for(unsigned i = 0; i < vec[n].size(); i++) 41 { 42 int son = vec[n][i]; 43 if(son == father && !flag) 44 { 45 flag = 1; 46 continue; 47 } 48 49 if(dfn[son] == -1) 50 { 51 tarjan_scc(son, n); 52 low[n] = min(low[n], low[son]); 53 } 54 else 55 low[n] = min(low[n], dfn[son]); 56 } 57 58 if(low[n] == dfn[n]) 59 { 60 int tmp; 61 do 62 { 63 tmp = S.top(); 64 id[tmp] = scc; 65 // cout << tmp << " "; 66 S.pop(); 67 }while(!S.empty() && tmp != n); 68 scc++; 69 //cout << endl << "---------------" << endl; 70 } 71 } 72 73 void deal_scc(int n, int &sol) 74 { 75 int u, v; 76 int du[MAXN] = {0}; 77 for(int i = 1; i <= n; i++) 78 { 79 for(unsigned j = 0; j < vec[i].size(); j++) 80 { 81 u = i, v = vec[i][j]; 82 if(id[u] == id[v]) 83 continue; 84 else 85 { 86 du[id[v]]++; du[id[u]]++; 87 } 88 } 89 } 90 int sum = 0; 91 for(int i = 1; i < scc; i++) 92 { 93 if(du[i] == 2) 94 sum++; 95 } 96 sum++; 97 sol = sum / 2; 98 } 99 100 int main(void) 101 { 102 #ifndef ONLINE_JUDGE 103 //freopen("in.txt", "r", stdin); 104 #endif 105 106 int n, m; 107 while(scanf("%d %d", &n, &m) == 2) 108 { 109 init(); 110 int u, v; 111 for(int i = 0; i < m; i++) 112 { 113 scanf("%d %d", &u, &v); 114 addEdge(u, v); 115 } 116 tarjan_scc(1, 1); 117 int sol; 118 deal_scc(n, sol); 119 printf("%d\n", sol); 120 //cout << "****************" << endl; 121 } 122 return 0; 123 }
//POJ3352 //State: POJ3352 Accepted 280K 47MS C++ 1865B //题意与上述的题一模一样
View Code
1 #include <iostream> 2 #include <vector> 3 #include <stack> 4 using namespace std; 5 6 const int MAXN = 1005; 7 8 vector<int> vec[MAXN]; 9 stack<int> S; 10 int dfn[MAXN], low[MAXN], step; 11 int id[MAXN], scc; 12 13 void init() 14 { 15 while(!S.empty()) 16 S.pop(); 17 18 step = 0; 19 scc = 1; 20 for(int i = 0; i < MAXN; i++) 21 { 22 id[i] = -1; 23 vec[i].clear(); 24 dfn[i] = low[i] = -1; 25 } 26 } 27 28 void addEdge(int u, int v) 29 { 30 vec[u].push_back(v); 31 vec[v].push_back(u); 32 } 33 34 void tarjan_scc(int n, int father) 35 { 36 dfn[n] = low[n] = ++step; 37 S.push(n); 38 int flag = 0; 39 for(unsigned i = 0; i < vec[n].size(); i++) 40 { 41 int son = vec[n][i]; 42 if(son == father && !flag) 43 { 44 flag = 1; 45 continue; 46 } 47 48 if(dfn[son] == -1) 49 { 50 tarjan_scc(son, n); 51 low[n] = min(low[n], low[son]); 52 } 53 else 54 low[n] = min(low[n], dfn[son]); 55 } 56 57 if(low[n] == dfn[n]) 58 { 59 int tmp; 60 do 61 { 62 tmp = S.top(); 63 id[tmp] = scc; 64 // cout << tmp << " "; 65 S.pop(); 66 }while(!S.empty() && tmp != n); 67 scc++; 68 //cout << endl << "---------------" << endl; 69 } 70 } 71 72 void deal_scc(int n, int &sol) 73 { 74 int u, v; 75 int du[MAXN] = {0}; 76 for(int i = 1; i <= n; i++) 77 { 78 for(unsigned j = 0; j < vec[i].size(); j++) 79 { 80 u = i, v = vec[i][j]; 81 if(id[u] == id[v]) 82 continue; 83 else 84 { 85 du[id[v]]++; du[id[u]]++; 86 } 87 } 88 } 89 int sum = 0; 90 for(int i = 1; i < scc; i++) 91 { 92 if(du[i] == 2) 93 sum++; 94 } 95 sum++; 96 sol = sum / 2; 97 } 98 99 int main(void) 100 { 101 #ifndef ONLINE_JUDGE 102 freopen("in3352.txt", "r", stdin); 103 #endif 104 105 int n, m; 106 while(scanf("%d %d", &n, &m) == 2) 107 { 108 init(); 109 int u, v; 110 for(int i = 0; i < m; i++) 111 { 112 scanf("%d %d", &u, &v); 113 addEdge(u, v); 114 } 115 tarjan_scc(1, 1); 116 int sol; 117 deal_scc(n, sol); 118 printf("%d\n", sol); 119 //cout << "****************" << endl; 120 } 121 return 0; 122 }