1、DFS,NUMI记录访问到 I 的时间戳,LOWI = MINNUMI, LOWQ存在 I-Q 的边且 Q 不是 I 的父节点然后就可以判断了,i 是割点当 i 是根节点且它有 2 个以上的儿子,或者它不是根节点且 lowq=numq(i,q)是桥当且仅当 lowqnumi#include#includeconst long maxn=10;long nummaxn;long lowmaxn;long colormaxn;long graphmaxnmaxn;bool cutmaxn;bool bridgemaxnmaxn;long now;long n;long cutnum;long br
2、idgenum;long fathermaxn;long childmaxn;void dfs(int);int main()int i, j;FILE *in=fopen( “input.txt“, “r“);FILE *out=fopen( “output.txt“, “w“);fscanf( in, “%d“, for ( i=1; i=numi) flag=true;if (lowqnumi)bridgeqi=true;bridgeiq=true;bridgenum+;colori=1;if (fatheri=0)cutnum+;求无向图的割点!2008-07-20 22:46 求割顶
3、(割点) ,主要的算法结构就是 DFS,一个点是割点,当且仅当以下两种情况:(1)该节点是根节点,且有两棵以上的子树(2)该节点的子节点中的任一个,没有到该节点祖先的反向边(就是说如果没有这个割顶,那么这个子节点和那个祖先之间就不能连通)实现的时候判断第一个条件只需要记录一下子树的数目就好第二个条件稍微麻烦,要用一个 ancestor 存和每个节点相连点的最小深度( 最高祖先的深度),deep 存当前点深度,判断时候如果 ancestori = deepfatheri就表示不存在反向边,那么 i 就是割点了。/lrj 书上的模板vectorv301;int c301,D301,a301,cut
4、301,root;/c记录点的颜色 ci=0:白色 ci=1:灰色 ci=2:黑色/D记录点的深度。a记录能达到的祖先的深度。cut 记录割点void dfs(int k,int f,int d)int tot,i,n=vk.size();ck=1;Dk=d;ak=d;tot=0;for(i=0;i1)|(k!=rootck=2;另:/最佳边割集#define MAXN 100#define inf 1000000000int max_flow(int n,int matMAXN,int source,int sink)int vMAXN,cMAXN,pMAXN,ret=0,i,j;for (
5、;)for (i=0;icj)j=i;if (jciif (jciif (jcifor (ret+=j=ci=sink;i!=source;i=pi)matpii-=j,matipi+=j;int min_vertex_cut(int n,int matMAXN,int source,int sink,int* set)int m0MAXNMAXN,mMAXNMAXN,i,j,k,ret=0,last;if (source=sink|matsourcesink)return -1;for (i=0;in+n;i+)for (j=0;jn+n;j+)m0ij=0;for (i=0;in;i+)for (j=0;jn;j+)if (matij)m0in+j=inf;for (i=0;in;i+)m0n+ii=1;for (i=0;in+n;i+)for (j=0;jn+n;j+)mij=m0ij;last=max_flow(n+n,m,source,n+sink);for (k=0;knk+)if (k!=sourcein+n;i+)for (j=0;jn+n;j+)mij=m0ij;mn+kk=0;if (max_flow(n+n,m,source,n+sink)last)setret+=k;m0n+kk=0; last-; return ret;