一、拓扑排序
leetcode 207. 课程表
维护一个数据结构用于存储图的入度或者出度的结构,每次删除入度=0的点及它的出度连线,直到不存在入度=0或者所有节点都已经删除为止。
具体实现时需要有一个标记数组标记已经删除的结点,存储每一个点的入度是多少,出度所连的点有哪些
struct discribe { int num; queue<int>node; }; class Solution { public: bool canFinish(int numCourses, vector<vector<int>>& prerequisites) { int lable[numCourses]; memset(lable,0,sizeof(lable)); map<int,struct discribe>inner; for(int i=0;i<numCourses;i++)//舒适化 { inner[i].num=0; queue<int> tmp; inner[i].node=tmp; } for(int i=0;i<prerequisites.size();i++) { queue<int> tmp; tmp=inner[prerequisites[i][1]].node;//1是前点 0是后点 tmp.push(prerequisites[i][0]); inner[prerequisites[i][0]].num++;//给后点的入度+1 inner[prerequisites[i][1]].node=tmp;//接在后面的点集合 } while(true) { int loop_or_not=0; for(int i=0;i<numCourses;i++) { if(lable[i]==1||inner[i].num!=0) continue; queue<int> tmp=inner[i].node; while(tmp.size()) { inner[tmp.front()].num--; tmp.pop(); } lable[i]=1; loop_or_not=1; break; } if(loop_or_not==0)//扫面一遍以后不在有更新 break; } for(int i=0;i<numCourses;i++) { if(lable[i]==0) return false; } return true; } };
二、并查集
leetcode 684. 冗余连接
map存当前节点的直接father是谁,通过循环查找每一个节点的祖先,如果是冗余边,该边所连的两个点有共同祖先
无向图的father更新策略1:首先每个点的father初始化为自己,设置标记数组记录当前点是否被其他点当作father,被当作过father的优先做别人的儿子,如果两个都做过father,就把这两个点的祖先连在一起
无向图的father更新策略2:寻找这两个点的祖先,把这两个点的祖先连在一起即可
路径压缩:每通过循环查询一次祖先,就把祖先当作查询点的father
class Solution { public: map<int,int>donser; int find_source(int x)//寻找祖先 { int tmp=x; while(donser[x]!=x) x=donser[x]; donser[tmp]=x;//路径压缩 return x; } vector<int> findRedundantConnection(vector<vector<int>>& edges) { int lable[1001]; for(int i=0;i<=edges.size();i++) { donser[i]=i; lable[i]=0; } for(int i=0;i<edges.size();i++) { int x=find_source(edges[i][0]); int y=find_source(edges[i][1]); if(x==y) return edges[i]; /*if(edges[i][0]==x&&lable[edges[i][1]]==0) { donser[edges[i][0]]=edges[i][1]; lable[edges[i][1]]=1; } else if(edges[i][1]==y&&lable[edges[i][0]]==0) { donser[edges[i][1]]=edges[i][0]; lable[edges[i][0]]=1; } else*/ donser[x]=y; } return edges[edges.size()-1]; } };