题目的意思就是让你就割点,并且求出去掉这个割点可以形成几个连通分量。
我的思路是遍历每一个点,如果把这个点去掉会会不会形成多个连通分量,会的话求出来,用dfs可以遍历和
其中个点相连的所有点(去掉一点后)让这个连通分量标记为1,以此类推其它的标记2.3.....
我刚开始的时候直接用邻接矩阵存图,然后dfs,结果就T了,刚开始没多想,后来看了一下O(n^3)以上的
然后就来百度题解了,看了一下基本上是用求割点的算法,代码都很长。
然后有一个博文提示用邻接表,我就改了,果然快很多,然后就wa了两次
后来才发现这题目很坑,就是他的标号是不一定按顺序的
就是可能会出现这样的数据:
1 3
1 5
0
改完以后就过了
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int mx(int a,int b){return a>b?a:b;}
const int N=1010;
typedef struct node node;
struct node
{
int no,part;
};
node p[N];
int psize;
vector<int >g[N];
int n;
int flag[N];
void dfs(int x,int level)
{
int j,i;
flag[x]=level;
for(i=0;i<g[x].size();i++){
j=g[x][i];
if(!flag[j])
dfs(j,level);
}
}
void get(int x)
{
int j,i,level,k;
memset(flag,0,sizeof(flag));
level=0;
flag[x]=1;
for(i=0;i<n;i++)
{
if(i!=x&&!flag[i]&&g[i].size()>0){
flag[i]=++level; //记录连通分量个数
for(j=0;j<g[i].size();j++){
k=g[i][j];
if(!flag[k])
dfs(k,level);
}
}
}
if(level>1)
{
p[psize].no=x+1;
p[psize].part=level;
psize++;
}
}
int main()
{
int a,b,i,k=1;
while(scanf("%d",&a),a)
{
scanf("%d",&b);
memset(g,0,sizeof(g));
n=mx(a,b);
g[a-1].push_back(b-1);
g[b-1].push_back(a-1);
while(scanf("%d",&a),a)
{
if(a>n)n=a;
scanf("%d",&b);
if(b>n)n=b;
g[a-1].push_back(b-1);
g[b-1].push_back(a-1);
}
psize=0;
for(i=0;i<n;i++)
get(i);
printf("Network #%d\n",k++);
if(psize)
for(i=0;i<psize;i++)
printf(" SPF node %d leaves %d subnets\n",p[i].no,p[i].part);
else printf(" No SPF nodes\n");
printf("\n");
}
return 0;
}