- #ifndef _ALGORITHM_H_2008_
- #define _ALGORITHM_H_2008_
- #include "Graph.h"
- //深度优先遍历算法
- template<bool pre,class FirstArg,class ResultType>
- void DFS(Graph& graph,Graph::size_t start,const pointer_to_unary_function<FirstArg,ResultType>& _func){
- graph.visit(graph[start]);
- Vertex& ve=graph[start];
- if(pre && &_func!=NULL){
- _func(ve);
- }
- for(Edge* e=ve.getFirstEdge();e!=NULL;e=ve.getNextEdge(*e)){
- if(!graph.isVisited(e->getTarget().getIndex())){
- DFS<pre>(graph,e->getTarget().getIndex(),_func);
- graph.visit(*e);
- }
- }
- if(!pre&& &_func!=NULL)
- _func(ve);
- }
- //广度优先遍历算法
- template<class FirstArg,class ResultType>
- void BFS(Graph& graph,Graph::size_t start,const pointer_to_unary_function<FirstArg,ResultType>& _func){
- assert(start<graph.getVerticesNum());
- graph.clearState();
- typedef Graph::Reference reference;
- queue<int> vertexQueue;
- graph.visit(graph[start]);
- if(&_func!=NULL)
- _func(graph[start]);
- vertexQueue.push(start);
- while(!vertexQueue.empty()){
- reference ve=graph[vertexQueue.front()];
- vertexQueue.pop();
- for(Edge* e=ve.getFirstEdge();e!=NULL;e=ve.getNextEdge(*e)){
- Graph::size_t index=e->getTarget().getIndex();
- if(!graph.isVisited(index)){
- graph.visit(graph[index]);
- graph.visit(*e);
- if(&_func!=NULL)
- _func(graph[index]);
- vertexQueue.push(index);
- }
- }
- }
- graph.clearState();
- }
- //拓扑顺序遍历
- template<class FirstArg,class ResultType>
- bool Toplogic(Graph& graph,const pointer_to_unary_function<FirstArg,ResultType> _func){
- int* inDegree=new int[graph.getVerticesNum()];
- queue<int> veQueue;
- for(int i=0;i<graph.getVerticesNum();i++){
- inDegree[i]=graph[i].getInDegree();
- if(inDegree[i]==0)
- veQueue.push(i);
- }
- int sum=0;
- while(!veQueue.empty()){
- int v=veQueue.front();
- veQueue.pop();
- graph.visit(graph[v]);
- if(&_func!=NULL)
- _func(graph[v]);
- sum++;
- for(Edge* e=graph[v].getFirstEdge();e!=NULL;e=graph[v].getNextEdge(*e)){
- int i=e->getTarget().getIndex();
- inDegree[i]--;
- if(inDegree[i]==0)
- veQueue.push(i);
- }
- }
- if(sum!=graph.getVerticesNum()){
- printf("图中存在环");
- return false;
- }
- return true;
- }
- void popStack(Graph& graph,vector<int>& vStack,int u,vector<vector<Vertex*>>& block){
- vector<Vertex*> newBlock;
- while(!vStack.empty()){
- int index=vStack.back();
- newBlock.push_back(&graph[index]);
- vStack.pop_back();
- if(index==u)
- break;
- }
- block.push_back(newBlock);
- }
- //寻找图的割点和最大块
- //low[u]=|__dfn[u] u was firstly visited
- // |__min(low[u],dfn[w]) uw was edge which w has been visited
- // |__min(low[u],low[s]) all of the edges of u's son has been checked
- //1 if a root has not only one child then this root is a cutvertex
- //2 if low[u]>=low[father[u]] then u is a cutvertex
- void FindCutVertexAndBlock(Graph& graph,vector<Vertex*>& cutVertex,vector<vector<Vertex*>>& block){
- graph.clearState();
- int vertexSize=graph.getVerticesNum();
- int* dfn=new int[vertexSize];
- memset(dfn,0,vertexSize*sizeof(int));
- int* low=new int[vertexSize];
- memset(low,0,vertexSize*sizeof(int));
- int* father=new int[vertexSize];
- memset(father,0,vertexSize*sizeof(int));
- vector<int> vertexStack;
- int u=0; //初始访问节点
- bool reflashStack=true;
- Edge* e=NULL;
- int i=1;
- while(true){
- if(reflashStack){
- dfn[u]=i;
- low[u]=i;
- vertexStack.push_back(u);
- e=graph[u].getFirstEdge();
- i++;
- }
- else
- reflashStack=true;
- for(;e!=NULL;e=graph[u].getNextEdge(*e))
- if(!graph.isVisited(*e))
- break;
- if(e!=NULL) //有未使用的边
- {
- graph.visit(*e);
- int v=e->getTarget().getIndex();
- if(dfn[v]==0){ //v是子节点,访问
- father[v]=u; //u是v的父节点
- u=v;
- }
- else{ //u-v是一条指向已经被访问过的节点的边
- low[u]=min(low[u],dfn[v]); //如果v在u之前被访问过,则low[u]指向v
- reflashStack=false; //u节点不重新入栈
- }
- continue;
- }
- else{ //u的所有子节点都被访问
- if(dfn[father[u]]==1)//u的父节点是初始节点,
- {
- popStack(graph,vertexStack,father[u],block);
- e=graph[father[u]].getFirstEdge();
- for(;e!=NULL;e=graph[father[u]].getNextEdge(*e))
- if(!graph.isVisited(*e))
- break;
- if(e!=NULL){ //根节点还有未使用的边,根是割点
- u=father[u];
- cutVertex.push_back(&graph[u]);
- reflashStack=false;
- continue;
- }
- else{
- int * first=find(dfn,dfn+graph.getVerticesNum(),0);
- u=first-dfn;
- if(u>=graph.getVerticesNum() || u<0)
- break;
- continue;
- }
- }
- else{
- reflashStack=false;
- if(low[u]<dfn[father[u]]){ //u节点的指向节点比u的父节点小,更新父节点指向
- low[father[u]]=min(low[father[u]],low[u]);
- u=father[u]; //u遍历完毕,回溯
- }
- else{ //u的子节点S没有到u的祖先节点的后向边,u是割点,u以上的节点形成块
- u=father[u];
- popStack(graph,vertexStack,u,block);
- cutVertex.push_back(&graph[u]);
- }
- }
- }
- }
- graph.clearState();
- }
- //寻找图的最大连通子图
- int FindGreatestConnectedSubGraph(Graph& graph,vector<vector<Vertex*>>& subGraph){
- graph.clearState();
- int vertexSize=graph.getVerticesNum();
- int* dfn=new int[vertexSize];
- memset(dfn,0,vertexSize*sizeof(int));
- int* low=new int[vertexSize];
- memset(low,0,vertexSize*sizeof(int));
- int* father=new int[vertexSize];
- memset(father,-1,vertexSize*sizeof(int));
- vector<int> vertexStack;
- int u=0; //初始访问节点
- bool reflashStack=true;
- Edge* e=NULL;
- int i=1;
- int maxIndex=-1;
- int maxSize=0;
- while(true){
- if(reflashStack){
- dfn[u]=i;
- low[u]=i;
- vertexStack.push_back(u);
- e=graph[u].getFirstEdge();
- i++;
- }
- else
- reflashStack=true;
- for(;e!=NULL;e=graph[u].getNextEdge(*e))
- if(!graph.isVisited(*e))
- break;
- if(e!=NULL) //有未使用的边
- {
- graph.visit(*e);
- int v=e->getTarget().getIndex();
- if(dfn[v]==0){ //未访问的子节点
- father[v]=u;
- u=v;
- continue;
- }
- else if(dfn[v]<dfn[u] && find(vertexStack.begin(),vertexStack.end(),v)!=vertexStack.end()){
- low[u]=min(low[u],low[v]);
- reflashStack=false;
- }
- else
- reflashStack=false;
- }
- else{
- if(low[u]==dfn[u]){ //极大连通子图
- popStack(graph,vertexStack,u,subGraph);
- if(subGraph.back().size()>maxSize){
- maxSize=subGraph.back().size();
- maxIndex=subGraph.size()-1;
- }
- }
- if(father[u]>=0){
- low[father[u]]=min(low[father[u]],low[u]);
- u=father[u];
- reflashStack=false;
- }
- else{
- int* first=find(dfn,dfn+graph.getVerticesNum(),0);
- u=first-dfn;
- if(u>=graph.getVerticesNum() || u<0)
- break;
- }
- }
- }
- return maxSize;
- }
- #endif

被折叠的 条评论
为什么被折叠?



