题目大意:找出一个网络中的spf点,即割点,并输出将某spf点删除后会将原网络分割成几个连通的子网络。
即求割点,用tarjan算法。
#include <stdio.h> #include <string.h> int min(int a,int b) { if(a<b) return a; else return b; } int Edge[1001][1001]; int vis[1001]; int nodes; //节点数目 int tmpdfn; //深度优先数 int dfn[1001]; //各节点的深度优先数 int low[1001]; // low[i]表示节点i可以通过它的子女节点所能到达的深度优先数最低的节点 int son; //记录根节点有几个子女 int subnet[1001]; //subnet[i]表示去除该节点后原网络会分割成几个连通的子网络 void dfs(int u) { int v; for(v=1;v<=nodes;v++) { if(Edge[u][v]) { if(!vis[v]) { vis[v]=1; tmpdfn++; dfn[v]=low[v]=tmpdfn; dfs(v); low[u]=min(low[v],low[u]); if(low[v]>=dfn[u]) { if(u!=1) subnet[u]++; if(u==1) son++; } } else low[u]=min(low[u],dfn[v]); } } } void init() { low[1]=dfn[1]=1; tmpdfn=1;son=0; memset(vis,0,sizeof(vis)); vis[1]=1; memset(subnet,0,sizeof(subnet)); } int main() { int i; int u,v; int find; int number=1; while(1) { scanf("%d",&u); if(u==0) break; memset(Edge,0,sizeof(Edge)); nodes=0; scanf("%d",&v); if(u>nodes) nodes=u; if(v>nodes) nodes=v; Edge[u][v]=Edge[v][u]=1; while(1) { scanf("%d",&u); if(u==0) break; scanf("%d",&v); if(u>nodes) nodes=u; if(v>nodes) nodes=v; Edge[u][v]=Edge[v][u]=1; } if(number>1) printf(" "); printf("Network #%d ",number); number++; init(); dfs(1); if(son>1) subnet[1]=son-1; find=0; for(i=1;i<=nodes;i++) { if(subnet[i]) { find=1; printf(" SPF node %d leaves %d subnets ",i,subnet[i]+1); } } if(!find) printf(" No SPF nodes "); } return 0; }