ZOJ 1119 SPF(tarjan求割点)

来源:互联网 发布:知乎经典语录 编辑:程序博客网 时间:2024/05/11 20:15

关于割点的内容参考这篇文章:http://www.byvoid.com/en/blog/biconnect/

/* 1、若深度优先生成树的根有两棵或两棵以上的子树,则此根顶点必定为关节点。*/  

/* 2、若生成树中某个非叶子顶点v,其孩子结点均没有指向 v 的祖先的回边,则 v 为关节点。*/  


#include <iostream>#include <cstdio>#include <memory.h>#include <algorithm>#include <vector>using namespace std;const int maxn=1010;struct edge{int v,next;}es[maxn];int dfn[maxn],low[maxn],head[maxn],idx,n,f;vector<pair<int,int> >ans;void init(){ans.clear();for (int i=1;i<=maxn;++i){head[i]=-1;}memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));idx=0;}void tarjan(int u,bool root){dfn[u]=low[u]=++idx;int cnt=0;for (int ne=head[u];ne!=-1;ne=es[ne].next){int v=es[ne].v;if(!dfn[v]){tarjan(v,false);low[u]=min(low[u],low[v]);if(root){//根节点特判cnt++;}else if(low[v]>=dfn[u]){//当前点是割点cnt++;//子树数量}}else{//回边,已经和其他节点构成了分支,不再计算low[u]=min(low[u],dfn[v]);}}if(root&&cnt>=2){ans.push_back(make_pair(u,cnt));}else if(!root&&cnt){ans.push_back(make_pair(u,cnt+1));}}void addEdge(int u,int v,int eidx){es[eidx].v=v;es[eidx].next=head[u];head[u]=eidx;}int main(){int u,v,cas=1;scanf("%d",&u);while (1){init();scanf("%d",&v);int eidx=0;addEdge(u,v,eidx++);addEdge(v,u,eidx++);while (scanf("%d",&u)&&u){scanf("%d",&v);addEdge(u,v,eidx++);addEdge(v,u,eidx++);}printf("Network #%d\n",cas++);f=0;tarjan(1,true);sort(ans.begin(),ans.end());if(ans.size()==0){printf("  No SPF nodes\n");}else{for (int i=0;i<ans.size();++i){printf("  SPF node %d leaves %d subnets\n",ans[i].first,ans[i].second);}}scanf("%d",&u);if(u==0)break;printf("\n");}return 0;}


原创粉丝点击