poj1523 求割点割边

来源:互联网 发布:信鸽营销软件 编辑:程序博客网 时间:2024/06/05 22:42

以下内容为个人理解,有错误地方还请指出。



求割点

点u是割点的充分条件:

1. 如果u是dfs树的根,则u至少有两个子女。

2. 如果u不是dfs树的根,则它至少有一个子女w,从w出发,不可能通过和w、w的子孙相连的回边到达u的祖先。

 

u是割点的充要条件是:u或则是具有两个以上子女的深度优先生成树的根,或则虽然不是根,但它有一个子女w,使得low[w]>=dfn[u]。

 

求割边

有两种判断方法:

1. 当点u的子女v满足low[v]>dfn[u] 时,(u,v),(v,u)是一条割边;

2. 当无向图G中u,v相连,但是low[u]!=low[v]时,(u,v),(v,u)是一条割边。(因为同一边双连通分量的点,low值相同,详细可参考缩点)



//tarjan算法模板vector<int>head[maxn];//邻接表tarjan_dfs(int rt,int father)//father为rt的父节点{int son=0;//rt的子女数dfn[rt]=low[rt]=dep_tmp++;vis[rt]=true;for(int i=0,len=head[rt].size();i<len;++i){                int v=head[rt][i];if(!vis[v]){son++;tarjan_dfs(v,rt);low[rt]=min(low[rt],low[v]);}else if(v!=father)//不要原路返回{low[rt]=min(low[rt],dfn[v]);}if(  (rt!=root && low[v]>=dfn[rt] )|| (rt==root && son>1) ){cut[rt]=true;//标记割点}                if( low[v]>dfn[rt]        {                        cut_edge[rt][v]=true;//标记割边                        cut_edge[v][rt]=true;                }}}



Poj1523 SPF给定一个连通网络(无向图),网络的结点数<=1000,求出这个网络的所有割点编号,并求出若删去其中一个割点k后,对应的,原网络会被分割为多少个连通分量class  POJ_1523{protected:bool _map[maxn][maxn];int low[maxn];//特点int dfn[maxn];//点的dfs序号bool cut[maxn];//标记是否为割点bool vis[maxn];int dep_tmp;int root;//dfs起点 这里我设置为最小的点int size;//最大点的标号+1int I;public:int input();bool solve();void initial();void dfs_net(int rt);void tarjan_dfs(int rt,int father);POJ_1523() {I=1;while(solve());}};void POJ_1523::initial(){mem(_map); mem(low); mem(dfn); mem(vis); mem(cut);dep_tmp=1;}int POJ_1523::input(){int x,y,num=0;root=maxn; size=0;while(scanf("%d",&x)&&x){num++;scanf("%d",&y);root=min(root,min(x,y));size=max(size,max(x+1,y+1));_map[x][y]=_map[y][x]= true;}return num;}void POJ_1523::tarjan_dfs(int rt,int father){int son=0;dfn[rt]=low[rt]=dep_tmp++;vis[rt]=true;for(int i=1;i<size;++i){if(_map[rt][i]){if(!vis[i]){son++;tarjan_dfs(i,rt);low[rt]=min(low[rt],low[i]);}else if(i!=father)//如果不是父节点,那就是一条回边low[rt]=min(low[rt],dfn[i]);if( (rt==root && son>1) ||  (rt!=root && low[i]>=dfn[rt]) )cut[rt]=true;}}}bool POJ_1523::solve(){initial();if(!input())return false;int i;for(i=1;i<size;++i){if(!vis[i])//只进一次 因为图是联通的tarjan_dfs(i,i);}if(I!=1)printf("\n");printf("Network #%d\n",I++);bool flag=false;for(i=root;i<size;++i){if(cut[i]){mem(vis);vis[i]=true;int j,subnet_num=0;for(j=root;j<size;++j){if(_map[j][i]&&!vis[j]){subnet_num++;dfs_net(j);}}printf("  SPF node %d leaves %d subnets\n",i,subnet_num);flag=true;}}if(!flag)printf("  No SPF nodes\n");return true;}void POJ_1523::dfs_net(int rt){vis[rt]=true;int i;for(i=root;i<size;++i){if(!vis[i]&&_map[i][rt])dfs_net(i);}}int main() {  POJ_1523 final_ans;  }


0 0
原创粉丝点击