POJ3177 && POJ3352_加最好的边构成双连通图

/*
*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 }

转载于:https://www.cnblogs.com/cchun/archive/2012/08/16/2641129.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值