POJ 1523 SPF 割边与割点
2013-07-14 13:08
351 查看
本题要求出割点,并算出每个割点将图分成几个分支。
用tarjan算法求的割点,然后对每个割点,dfs求有多少个分支
每点的数是不一定的,我用的set存的点,vector存的图
求多少个分支就是:如果i是割点,就对与i相连的点的分支进行dfs标记,
假如与i相连的第j个点标记完了,标记第j+1个点时,发现j+1点标记过了,则j+1点和之前的某点在同一分支上,则不 sum++;
大概就是这样,自己画图感受一下吧!
注意:每组用例后腰输出一个空行,”那个“之前还有两个空格
刚才又和同学交流了一下,求割点的分支那个不用dfs,
对于割点u,找i的儿子v,也就是点v满足f[v]==u,如果low[v]>=dfn[u],则sum++; 具体原理我也不是太懂。。自己研究一下吧
另外,如果u是根节点,则不用sum++,如果u不是根节点,他的父亲还有一个分支,所以要sum++;
用tarjan算法求的割点,然后对每个割点,dfs求有多少个分支
每点的数是不一定的,我用的set存的点,vector存的图
求多少个分支就是:如果i是割点,就对与i相连的点的分支进行dfs标记,
假如与i相连的第j个点标记完了,标记第j+1个点时,发现j+1点标记过了,则j+1点和之前的某点在同一分支上,则不 sum++;
大概就是这样,自己画图感受一下吧!
注意:每组用例后腰输出一个空行,”那个“之前还有两个空格
#include<stdio.h> #include<string.h> #include<algorithm> #include<vector> #include<set> using namespace std; set<int> s; int low[1010],dfn[1010],vis[1010],shi[1010]; int f[1010]; vector<int> q[1010]; int n,m,ntime,root,flag,flag1;//flag判断是否有割点,flag1判断是否输入结束 void dfs(int u,int fa)//递归标记被走过的点 { for(int i=0;i<q[u].size();i++){ int v=q[u][i]; if(v!=fa && shi[v]==0) { shi[v]=1; dfs(v,u); } } } void tarjan(int u,int father)//求low[]和dfn[] { f[u]=father; int i,j,k; low[u]=dfn[u]=ntime++; for(i=0;i<q[u].size();i++){ int v=q[u][i]; if(!dfn[v]){ tarjan(v,u); low[u]=min(low[u],low[v]); } else if(father!=v) low[u]=min(low[u],dfn[v]); } } void count() { int nroot=0,i; tarjan(root,0); set<int>::iterator it=s.begin(); for(it++;it!=s.end();it++){ int v=f[*it]; if(v==root) nroot++; else{ if(dfn[v]<=low[*it]) { vis[v]=1; flag=1; } } } if(nroot>1) { vis[root]=1; flag=1; } int sum; for(it=s.begin();it!=s.end();it++){ if(vis[*it]==1){ memset(shi,0,sizeof(shi)); sum=0; int u=*it; shi[u]=1; for(i=0;i<q[u].size();i++){ int v=q[u][i]; if(shi[v]==0)//与个点相连的v点没标记过 { sum++; shi[v]=1;//标记该点 dfs(v,u);//标记以该点为根节点的分支 } } printf(" SPF node %d leaves %d subnets\n",u,sum); } } } int main() { int i,j,k,ans=0; memset(vis,0,sizeof(vis));//各种初始化 memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(f,0,sizeof(f)); for(i=0;i<1010;i++) q[i].clear(); s.clear(); flag=0; flag1=0; while(scanf("%d",&n)!=EOF){ if(n!=0) { flag1=1; scanf("%d",&m); q .push_back(m); q[m].push_back(n); s.insert(n); s.insert(m); continue; } if(flag1==0) break; set<int>::iterator it=s.begin(); root=*it; ntime=1; ans++; printf("Network #%d\n",ans); count(); if(flag==0) printf(" No SPF nodes\n"); printf("\n"); memset(vis,0,sizeof(vis));//各种初始化 memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(f,0,sizeof(f)); for(i=0;i<1010;i++) q[i].clear(); s.clear(); flag=0; flag1=0; } return 0; }
刚才又和同学交流了一下,求割点的分支那个不用dfs,
对于割点u,找i的儿子v,也就是点v满足f[v]==u,如果low[v]>=dfn[u],则sum++; 具体原理我也不是太懂。。自己研究一下吧
另外,如果u是根节点,则不用sum++,如果u不是根节点,他的父亲还有一个分支,所以要sum++;
#include<stdio.h> #include<string.h> #include<algorithm> #include<vector> #include<set> using namespace std; set<int> s; int low[1010],dfn[1010],vis[1010]; int f[1010]; vector<int> q[1010]; int n,m,ntime,root,flag,flag1; void tarjan(int u,int father) { f[u]=father; int i,j,k; low[u]=dfn[u]=ntime++; for(i=0;i<q[u].size();i++){ int v=q[u][i]; if(!dfn[v]){ tarjan(v,u); low[u]=min(low[u],low[v]); } else if(father!=v) low[u]=min(low[u],dfn[v]); } } void count() { int nroot=0,i; tarjan(root,0); set<int>::iterator it=s.begin(); for(it++;it!=s.end();it++){ int v=f[*it]; if(v==root) nroot++; else{ if(dfn[v]<=low[*it]) { vis[v]=1; flag=1; } } } if(nroot>1) { vis[root]=1; flag=1; } int sum; for(it=s.begin();it!=s.end();it++){ if(vis[*it]==1){ sum=0; int u=*it; if(u!=root) //如果是根节点,则不用sum++,如果不是根节点,他的父亲还有一个分支,所以要sum++; sum++; for(i=0;i<q[u].size();i++){ int v=q[u][i]; if(f[v]==u && low[v]>=dfn[u]) //这判断一下 { sum++; } } printf(" SPF node %d leaves %d subnets\n",u,sum); } } } int main() { int i,j,k,ans=0; memset(vis,0,sizeof(vis)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(f,0,sizeof(f)); for(i=0;i<1010;i++) q[i].clear(); s.clear(); flag=0; flag1=0; while(scanf("%d",&n)!=EOF){ if(n!=0) { flag1=1; scanf("%d",&m); q .push_back(m); q[m].push_back(n); s.insert(n); s.insert(m); continue; } if(flag1==0) break; set<int>::iterator it=s.begin(); root=*it; ntime=1; ans++; printf("Network #%d\n",ans); count(); if(flag==0) printf(" No SPF nodes\n"); printf("\n"); memset(vis,0,sizeof(vis)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(f,0,sizeof(f)); for(i=0;i<1010;i++) q[i].clear(); s.clear(); flag=0; flag1=0; } return 0; }
相关文章推荐
- POJ1523:SPF——题解
- poj1523 SPF 双连通求割点
- poj1523 SPF
- 【poj 1523】SPF 【Greater New York 2000】
- poj_1523 SPF (求割点)
- poj 1523 SPF
- POJ 1523 SPF 找割点
- POJ 1523 SPF 割点
- [学习][poj1523]割点 SPF
- POJ 1523 SPF 求割点的好(板子)题!
- 【POJ】1523 SPF 割点
- POJ--1523 SPF(割点)
- POJ1523 SPF(割点模板)
- POJ 1523 SPF(无向图连通分量求割点)
- POJ 1523 SPF
- POJ1523 SPF
- POJ 1523 SPF 求割点
- POJ1523 SPF 求割点及连通块数 tarjin算法
- POJ 1523 SPF(求割点)
- poj 1523 SPF 输出割点及割点分割的点集数目