TOJ 2299. Electricity【求无向图割点】

公告:博客新增直接引用代码功能         专访谭海燕:移动互联网开发的那些事       CSDN博客频道自定义域名、标签搜索功能上线啦!    
 

TOJ 2299. Electricity【求无向图割点】

分类: 【图论专辑】   112人阅读  评论(0)  收藏  举报

 

/* 给出一个无向图,计算去掉一个点后所能得到的最大块数

 

 * 1)由于图可能不连通,先DFS求出图的块数num

 

 * 2)然后进行DFS求出割点并且存下割点将连通分支分成的块数f[i]

 

 * 3)找到最大的f[i]和num相加-1即为所求

 

 */

 

 

Code:

[cpp]  view plain copy
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <vector>  
  4. #define MAXN 10002  
  5. using namespace std;  
  6. int f[MAXN],low[MAXN],dep[MAXN];  
  7. bool flag[MAXN];  
  8. int n,depth,root,father,num;  
  9. vector<int>mapp[MAXN];  
  10. void DFS(int m){                        //鎵惧埌鏈€鍒濆浘鐨勫潡鏁?  
  11.     int i,u;  
  12.     flag[m] = true;  
  13.     for(i = 0;i < mapp[m].size(); i++){  
  14.         u = mapp[m][i];  
  15.         if(!flag[u])  
  16.             DFS(u);  
  17.     }  
  18. }  
  19. void DFS_CCS(int m){  
  20.     int i,u;  
  21.     low[m] = dep[m] = depth++;  
  22.     flag[m] = true;  
  23.     for(i = 0;i < mapp[m].size(); i++){  
  24.         u = mapp[m][i];  
  25.         if(!flag[u]){  
  26.             son ++;  
  27.             DFS_CCS(u);  
  28.             if(low[u] >= dep[m] && m != father) f[m] ++;  
  29.             else if(m == father && son > 1) f[m]++;   
  30.             if(low[m] > low[u]) low[m] = low[u];  
  31.         }  
  32.         else if(low[m] > dep[u]) low[m] = dep[u];  
  33.               
  34.     }  
  35.     if(m != father) f[m]++;  
  36. }  
  37. void cal(){  
  38.     int i,j;  
  39.     num = 0;  
  40.     memset(flag,false,sizeof(flag));  
  41.     for(i = 0;i < n; i++)  
  42.         if(!flag[i]){  
  43.             DFS(i);  
  44.             num++;  
  45.         }  
  46. }  
  47. void cal_ccs(){  
  48.     int i,j,son;  
  49.     memset(flag,false,sizeof(flag));  
  50.     memset(low,0,sizeof(low));  
  51.     memset(f,0,sizeof(f));  
  52.     memset(dep,0,sizeof(dep));  
  53.     depth = 0; num = 0;   
  54.     for(i = 0;i < n; i++)  
  55.         if(!flag[i]){  
  56.             num ++; son = 0;  
  57.             father = i;  
  58.             DFS_CCS(i);  
  59.         }  
  60. }  
  61. int main()  
  62. {  
  63.     int i,j,k,m;  
  64.     while(scanf("%d%d",&n,&m)){  
  65.         if(m == 0 && n == 0)break;  
  66.         for(i = 0;i < n; i++) mapp[i].clear();  
  67.         while(m--){  
  68.             scanf("%d%d",&i,&j);  
  69.             mapp[i].push_back(j);  
  70.             mapp[j].push_back(i);  
  71.         }  
  72.         cal();  
  73.         cal_ccs();  
  74.         int mm = 0;  
  75.         for(i = 0;i < n; i++)  
  76.             if(f[i] > mm)  
  77.                 mm = f[i];  
  78.         printf("%d/n",mm + num-1);  
  79.     }  
  80. }  
 

另一种写法简单些:

 

 * 1)每次DFS时num++,表示图的块数,然后在DFS过程中求出割点并且存下去掉割点   *   连通分量增加的块数,

注意根节点的f[root]最后要-1,因为1个儿子的根节点不  *   会增加图的块数

 

 * 2)找到最大的f[i]和num相加即为所求,但是注意考虑特殊情况,零图

 

 */

[cpp]  view plain copy
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <vector>  
  4. #define MAXN 10002  
  5. using namespace std;  
  6. int f[MAXN],low[MAXN],dep[MAXN];  
  7. bool flag[MAXN];  
  8. int n,depth,root,father,num,son;  
  9. vector<int>mapp[MAXN];  
  10. void DFS_CCS(int m){  
  11.     int i,u;  
  12.     low[m] = dep[m] = depth++;  
  13.     flag[m] = true;  
  14.     for(i = 0;i < mapp[m].size(); i++){  
  15.         u = mapp[m][i];  
  16.         if(!flag[u]){  
  17.             DFS_CCS(u);  
  18.             if(low[u] >= dep[m]) f[m] ++;  
  19.             if(low[m] > low[u]) low[m] = low[u];  
  20.         }  
  21.         else if(low[m] > dep[u]) low[m] = dep[u];  
  22.               
  23.     }  
  24. }  
  25. void cal_ccs(){  
  26.     int i,j;  
  27.     memset(flag,false,sizeof(flag));  
  28.     memset(low,0,sizeof(low));  
  29.     memset(f,0,sizeof(f));  
  30.     memset(dep,0,sizeof(dep));  
  31.     depth = 0; num = 0;   
  32.     for(i = 0;i < n; i++)  
  33.         if(!flag[i]){  
  34.             num ++;   
  35.             son = 0;  
  36.             father = i;  
  37.             DFS_CCS(i);  
  38.             if(f[father] != 0) f[father]--;  
  39.         }  
  40. }  
  41. int main()  
  42. {  
  43.     int i,j,k,m;  
  44.     while(scanf("%d%d",&n,&m)){  
  45.         if(m == 0 && n == 0)break;  
  46.         for(i = 0;i < n; i++) mapp[i].clear();  
  47.         while(m--){  
  48.             scanf("%d%d",&i,&j);  
  49.             mapp[i].push_back(j);  
  50.             mapp[j].push_back(i);  
  51.         }  
  52.         cal_ccs();  
  53.         if(num == n) printf("%d/n",n-1);           //注意考虑零图的情况  
  54.         else{   
  55.             int mm = 0;  
  56.             for(i = 0;i < n; i++)  
  57.                 if(f[i] > mm)  
  58.                     mm = f[i];  
  59.             printf("%d/n",mm + num);  
  60.         }  
  61.     }  
  62. }  

你可能感兴趣的:(【图论专辑】)