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

 

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

 

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

 

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

 

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

 

 */

 

 

Code:

#include <cstdio> #include <cstring> #include <vector> #define MAXN 10002 using namespace std; int f[MAXN],low[MAXN],dep[MAXN]; bool flag[MAXN]; int n,depth,root,father,num; vector<int>mapp[MAXN]; void DFS(int m){ //鎵惧埌鏈€鍒濆浘鐨勫潡鏁? int i,u; flag[m] = true; for(i = 0;i < mapp[m].size(); i++){ u = mapp[m][i]; if(!flag[u]) DFS(u); } } void DFS_CCS(int m){ int i,u; low[m] = dep[m] = depth++; flag[m] = true; for(i = 0;i < mapp[m].size(); i++){ u = mapp[m][i]; if(!flag[u]){ son ++; DFS_CCS(u); if(low[u] >= dep[m] && m != father) f[m] ++; else if(m == father && son > 1) f[m]++; if(low[m] > low[u]) low[m] = low[u]; } else if(low[m] > dep[u]) low[m] = dep[u]; } if(m != father) f[m]++; } void cal(){ int i,j; num = 0; memset(flag,false,sizeof(flag)); for(i = 0;i < n; i++) if(!flag[i]){ DFS(i); num++; } } void cal_ccs(){ int i,j,son; memset(flag,false,sizeof(flag)); memset(low,0,sizeof(low)); memset(f,0,sizeof(f)); memset(dep,0,sizeof(dep)); depth = 0; num = 0; for(i = 0;i < n; i++) if(!flag[i]){ num ++; son = 0; father = i; DFS_CCS(i); } } int main() { int i,j,k,m; while(scanf("%d%d",&n,&m)){ if(m == 0 && n == 0)break; for(i = 0;i < n; i++) mapp[i].clear(); while(m--){ scanf("%d%d",&i,&j); mapp[i].push_back(j); mapp[j].push_back(i); } cal(); cal_ccs(); int mm = 0; for(i = 0;i < n; i++) if(f[i] > mm) mm = f[i]; printf("%d/n",mm + num-1); } } 

另一种写法简单些:

 

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

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

 

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

 

 */

#include <cstdio> #include <cstring> #include <vector> #define MAXN 10002 using namespace std; int f[MAXN],low[MAXN],dep[MAXN]; bool flag[MAXN]; int n,depth,root,father,num,son; vector<int>mapp[MAXN]; void DFS_CCS(int m){ int i,u; low[m] = dep[m] = depth++; flag[m] = true; for(i = 0;i < mapp[m].size(); i++){ u = mapp[m][i]; if(!flag[u]){ DFS_CCS(u); if(low[u] >= dep[m]) f[m] ++; if(low[m] > low[u]) low[m] = low[u]; } else if(low[m] > dep[u]) low[m] = dep[u]; } } void cal_ccs(){ int i,j; memset(flag,false,sizeof(flag)); memset(low,0,sizeof(low)); memset(f,0,sizeof(f)); memset(dep,0,sizeof(dep)); depth = 0; num = 0; for(i = 0;i < n; i++) if(!flag[i]){ num ++; son = 0; father = i; DFS_CCS(i); if(f[father] != 0) f[father]--; } } int main() { int i,j,k,m; while(scanf("%d%d",&n,&m)){ if(m == 0 && n == 0)break; for(i = 0;i < n; i++) mapp[i].clear(); while(m--){ scanf("%d%d",&i,&j); mapp[i].push_back(j); mapp[j].push_back(i); } cal_ccs(); if(num == n) printf("%d/n",n-1); //注意考虑零图的情况 else{ int mm = 0; for(i = 0;i < n; i++) if(f[i] > mm) mm = f[i]; printf("%d/n",mm + num); } } }  

 

你可能感兴趣的:(TOJ 2299. Electricity【求无向图割点】)