Contents

  • 有向无环图
    • 定义
    • 性质
    • 应用
      • 最小路径点覆盖
      • 最小路径重复点覆盖
      • 路径独立集
      • 至少新添加几条边,使得DAG成为SCC

有向无环图

定义

性质

+ let HHH be the set of start-points and TTT the set of end-points in a Weakly-Connected-DAG;
. Any point (including H/TH/TH/T) must be reachable by at least one point of HHH and must can reach to at least one point of TTT;
. Any point a∈Ha \in Ha∈H and any point b∈Tb \in Tb∈T, aaa may not reach to bbb; e.g., (a→b)(a→c)(d→c)(a\to b) (a\to c) (d\to c)(a→b)(a→c)(d→c) where the start-point ddd cannot reach to the end-point bbb;

+ The 最大路径独立集 (it is a set of points such that any two points of it are not accessible to each other) of a DAG, maybe not the H/TH/TH/T where HHH is the set of start-points and TTT the set of end-points;
. e.g., (a→b)(a→c)(b→d)(c→d)(a\to b) (a \to c) (b\to d) (c\to d)(a→b)(a→c)(b→d)(c→d), the 最大路径独立集 is (b,c)(b,c)(b,c)

+ The transitive-graph of a DAG is also a DAG; (i.e., let E[a][b]E[a][b]E[a][b] denotes an edge in the DAG, then performing Floyd-Boolean to get a new graph GGG, finally GGG would also be a DAG)

+ Any path is DAG is Simple-Path (i.e., all points on the path are distinct);

+ The Source-Points of a DAG is the set of all points xxx such that din[x]=0din[ x] = 0din[x]=0, also the End-Points is all points dout[x]=0dout[x] = 0dout[x]=0;
. Any non-empty DAG must contains at least one Source-Points and End-Points. (let n,mn,mn,m be the number of Sources and Ends, then either n>0,m>0n>0, m>0n>0,m>0 or n=m=0n=m=0n=m=0, it is impossible that n=0,m>0n=0, m>0n=0,m>0)
. A point xxx is both Source and End if and only if xxx is a Isolated-Point.

+ Any two points a,ba,ba,b in a DAG maybe not Weakly-Connected (e.g., (1→2)(3)(1\to 2) (3)(1→2)(3) is a DAG); more precise, a,ba,ba,b either be Weakly-Connected, or Non-Connected; another phrase: a,ba,ba,b must be Non-Strongly-Connected.

+ (DAG can does Topological-Sorting) is equivalent with (Any graph that can does Topological-Sorting, must is a DAG)
. The Topological-Sequence of a DAG maybe not unique.


+ For any graph G=(V,E)G =(V,E)G=(V,E), after the performance Shrinking-SCC, it would becomes a DAG.
. Shrinking-SCC: let Id[v]Id[v]Id[v] denotes the SCC-ID of every point v∈Vv \in Vv∈V; Let G1=(V1,E1)G1 = (V1, E1)G1=(V1,E1) be a empty graph, and then iterating all edges (a→b)∈E(a \to b) \in E(a→b)∈E, add the edge Id[a]→Id[b]Id[a] \to Id[b]Id[a]→Id[b] into G1G1G1 when Id[a]≠Id[b]Id[a] \neq Id[b]Id[a]=Id[b]. Finally, G1G1G1 is a DAG.
. Moreover, G1G1G1 has no Loop, but may contains Multiple-Edge (you can use Hashing to avoid it when adding edges into G1G1G1);


For a Weakly-Connected DAG, let its Source be s1,s2,...,sns1,s2,...,sns1,s2,...,sn and its End be e1,e2,...,eme1,e2,...,eme1,e2,...,em;
We build a Bipartite-Graph where L=(s1,s2,...,sn),R=(e1,e2...,em)L = (s1,s2,..., sn), R = (e1,e2...,em)L=(s1,s2,...,sn),R=(e1,e2...,em); if sisisi can reach to ejejej, then we connected a edge between si,ejsi, ejsi,ej in the Bipartite;
As a result, the Maximal-Match of this Bipartite is min(n,m)min( n, m)min(n,m) (i.e., Full-Matched)
. Cuz any two points si,ejsi, ejsi,ej exists a path (i.e., if n<mn < mn<m, sisisi always has a Augmented-Path)

But if the DAG is not Weakly-Connected, it is not correct; e.g., if the DAG contains two Weakly-Connected-Sub-Graphs that are (2,3)(3,2)(2,3) (3,2)(2,3)(3,2) where (2,3)(2,3)(2,3) represents 222 Sources and 333 Ends;
The Maximal-Match is min(2,3)+min(3,2)=4min(2, 3) + min(3,2) = 4min(2,3)+min(3,2)=4, not min(2+3,3+2)=5min(2+3, 3+2) = 5min(2+3,3+2)=5

应用

最小路径点覆盖

If the graph is a DAG, 最小路径点覆盖 can be solved by Bipartite;

Let DDD be the DAG where all points are a1,a2,...,ana1,a2,...,ana1,a2,...,an, now we construct a Bipartite BBB using below method

for( (ai -> aj) : all edges in D){B.add( ai, aj +|V|);
}

In BBB, the L-Set are a1,...,ana1,...,ana1,...,an and R-Set are a1‾,...,an‾\overline{a1},...,\overline{an}a1,...,an where ai‾=a1+∣V∣\overline{ai} = a1 + |V|ai=a1+∣V∣ (no specific meaning, just making all ai‾\overline{ai}ai differs to aiaiai in the Bipartite); (if D is not DAG, B is also a Bipartite)

(最小路径点覆盖) equals ∣V∣−m|V| - m∣V∣−m where mmm is the Maximal-Match of BBB;

@Delimiter

证明

+ Cuz we only care about ∣S∣|S|∣S∣ where SSS is the 最小路径点覆盖, e.g., S=(a,b,c)(d,e)...S = (a,b,c) (d,e) ...S=(a,b,c)(d,e)... where every (...)(...)(...) denotes a path;
. We stipulate that a path (a,b,c)∈S(a,b,c) \in S(a,b,c)∈S actually denotes all paths with the form a→b→ca \to b \to ca→b→c (due to multiple edges between two points, so (a,b,c)(a,b,c)(a,b,c) may denotes many paths), it would not affect the calculation; cuz we focus on the number of ()()()() () ()()()(), not care about (?)(?)(?).
+ (路径点覆盖) →\to→ (Matches in Bipartite)
. (a1,a2,...ai)(ax,...)(..)...(a1,a2, ... ai) (ax,...) (..) ...(a1,a2,...ai)(ax,...)(..)... is a 路径点覆盖, where the points in all paths are distinct, any directed edge ai→ajai \to ajai→aj in any path had been transformed into undirected edge (ai−aj‾)(ai - \overline{aj})(ai−aj​) in BBB; we found that all such edges in BBB are disjoints, that is all these edges in BBB form a Match;
. e.g., a 路径点覆盖 (a,b,c)(d,e)(f)(a, b, c) (d, e) (f)(a,b,c)(d,e)(f) in DAG corresponds to a Match (a−b‾)(b−c‾)(d−e‾)(a-\overline{b}) (b-\overline{c}) (d- \overline{e})(a−b)(b−c)(d−e) in DDD;
. This map is Injective; (if D is not DAG, this is also satisfies)
+ (Matches in Bipartite) →\to→ (路径点覆盖)
. For a match (ai−aj‾)()()...(ai-\overline{aj}) () () ...(ai−aj​)()()..., cuz every edge (a−b‾)(a-\overline{b})(a−b) actually is a directed edge a→ba \to ba→b in DAG, from this view-point, firstly we write the match in the form (ai,aj‾)(xx,xx)...(ai,\overline{aj}) (xx,xx) ...(ai,aj​)(xx,xx)... where we call a (xx)(xx)(xx) be a path (corresponds to a Simple-Path in DAG); if there exists (a,b‾)(c,d‾)(a,\overline{b}) (c, \overline{d})(a,b)(c,d) where b=cb=cb=c, then merge them to be (a,b,d‾)(a, b, \overline{d})(a,b,d) (cuz two such edges a→b,b→ca\to b, b \to ca→b,b→c corresponds to a path a→b→ca\to b \to ca→b→c); proceeding this process, finally, every path is in the form (a1,a2,...,ak‾)(a1, a2, ..., \overline{ak})(a1,a2,...,ak) (a1≠aka1 \neq aka1=ak, cuz DAG has no circuit);
. All paths are distinct, that is there is no point belongs to multiple paths; Proof: (a1,a2,a3‾)(a4,a5,a6‾)(a1,a2,\overline{a3}) (a4,a5,\overline{a6})(a1,a2,a3)(a4,a5,a6) all a1,a2,a4,a5a1, a2, a4, a5a1,a2,a4,a5 (all points except the last-points) are distinct (due to they come from the left-set of original matches); all a2,a3‾,a5,a6‾a2, \overline{a3}, a5, \overline{a6}a2,a3,a5,a6 (all points except the first-points) are distinct (due to they also come from the right-set of the original matches); ai,aj‾ai, \overline{aj}ai,aj​ (aiaiai is the first-point in a path, aj‾\overline{aj}aj​ is the last-point in a path) are distinct (i.e., ai≠ajai \neq ajai=aj) (cuz the merge-process has finished, they must be in the same path, then it indicates that the path is a Circuit which is impossible is DAG)
. Finally, add all Isolated-Points; e.g., the match corresponds to paths (a1,a2,a3‾)(a4,a5‾)(a1,a2,\overline{a3}) (a4, \overline{a5})(a1,a2,a3)(a4,a5) (there are 777 points in total), then add the isolated points a6,a7a6, a7a6,a7; the new paths are (a1,a2,a3)(a4,a5)(a6)(a7)(a1,a2,a3) (a4,a5) (a6) (a7)(a1,a2,a3)(a4,a5)(a6)(a7) which is a 路径点覆盖
. Different matches correspond to different 路径点覆盖; so the map is Injective;

As a result, (路径点覆盖) and (matches) forms a Bijection;

Now, let’s consider the paths-count of a Match; all paths in a Match has two kinds (as mentioned above): 1 a self-path, i.e., a isolated-point (a)(a)(a), in this case, aaa must be a Unmatched-Point in L-Set under the match; 2 a path (a1,...,ai‾)(a1,...,\overline{ai})(a1,...,ai), then aiaiai (note that, not ai‾\overline{ai}ai must be a Unmatched-Point in L-Set under the match (if not (that is, it is a matched-point of L-Set), then it would be a non-last-point in a path, which would contradicts with the context ai‾\overline{ai}ai is a last-point);
. So, every path corresponds to a Unmatched-Point in L-Set; cuz these paths contains all points, so there would not exist a Unmatched-Point in L-Set with which no path corresponds;
. In a match, the paths-count equals the Unmatched-Points in L-Set, that is n−Mn - Mn−M where MMM is the match-count;

Therefore, 最小路径点覆盖 equals n−mn - mn−m where mmm is the maximal-match;

最小路径重复点覆盖

If the graph DDD is a DAG, (最小路径重复点覆盖) equals (最小路径点覆盖) in DDDDDD; where DDDDDD is the Transitivity-Graph of DDD (i.e., two edges a,ba,ba,b and b,cb,cb,c in DDD produce a new edge a,ca,ca,c)

@Delimiter

证明

A same stipulation as above, we use (a,b,c)(a,b,c)(a,b,c) denotes any path in the form a→b→ca\to b \to ca→b→c due to the multiple edges between two points; it would not affect, cuz we only focus on the paths-count, not the edges of a path;

If the graph DDD is a DAG, for a (路径重复点覆盖), we transform it to a Simplified-Form: if a point aaa occurs in two paths ...a......a......a... and ...a......a......a..., let’s focus on the first path 1 if aaa is the first-point or last-point (a,...a, ...a,... or ...,a... , a...,a) then remove this point from the path, all points are still coved; 2 if aaa is ...x,a,y...... x , a , y ......x,a,y..., then we use x,yx , yx,y to replace x,a,yx , a , yx,a,y (note that x,yx , yx,y no longer means a edge in DDD (cuz DDD may have no edge between them), it is just a transformation), now all points are still covered;
Finally, these paths cover all all points only once (that is, becomes a 路径点覆盖); but as discussed above, it is not a 路径点覆盖 of DDD (a path ...,x,y,......, x,y, ......,x,y,... in 路径点覆盖 where x,yx,yx,y must denotes a edge in a DAG, while there maybe no edge x,yx,yx,y in DDD);

So, we need to add such edges x,yx,yx,y into DDD (i.e., run Floyd-Boolean, two edges a,ba,ba,b and b,cb,cb,c produces a new edge a,ca,ca,c); the new graph would still be a DAG; let the new DAG be DDDDDD;

It can be proved that, 路径重复点覆盖 in DDD is equivalent to 路径重复点覆盖 in DDDDDD (cuz if a path uses an edge x,yx,yx,y in DDDDDD, then it can be decomposed into x,...,yx,...,yx,...,y where all edges are raw-edges)

As a result, any 路径重复点覆盖 in DDDDDD, using the above Simplified-Form operation, it can be transformed to a 路径点覆盖 in DDDDDD; and all 路径点覆盖 are also 路径重复点覆盖;
so we just calculate the 最小路径点覆盖 in DDDDDD which equals to the 最小路径重复点覆盖 in DDDDDD (also in DDD);

@Delimiter

例题

AcWing-379. 捉迷藏

路径独立集

If DDD is a DAG, (最大独立集) equals (最小路径重复点覆盖) in DDD;

@Delimiter

证明

@Unfinished

至少新添加几条边,使得DAG成为SCC

AcWing-367. 学校网络

For a DAG (V,E)(V, E)(V,E), let xxx denoted the answer;
1 x=0x = 0x=0 if ∣V∣=1|V| = 1∣V∣=1
2 otherwise x=max(s,e)x = max(s, e)x=max(s,e) where sss is the number of Source-Points and eee is the End-Points;


For a DAG GGG, let its Source be s1,s2,...,sns1,s2,...,sns1,s2,...,sn and its End be e1,e2,...,eme1,e2,...,eme1,e2,...,em; you can imagine that a graph BBB which consists of these points, and if sisisi can reach to ejejej then BBB has a edge si→ejsi \to ejsi→ej; BBB is also a DAG, and once you make BBB a SCC then GGG is also a SCC.
Proof: for any points a,ba,ba,b in GGG and suppose that s1→a→e1s1 \to a \to e1s1→a→e1 and s2→b→e2s2 \to b \to e2s2→b→e2 where →\to→ means can reach; cuz s1,s2,e1,e2s1,s2,e1,e2s1,s2,e1,e2 are Strongly-Connected, there exists two paths a→e1→s2→ba \to e1 \to s2 \to ba→e1→s2→b and b→e2→s1→ab \to e2 \to s1 \to ab→e2→s1→a, therefore a,ba,ba,b are Strongly-Connected;

A easy device is adding these edges si→si−1si \to s_{i-1}si→si−1​ and ei→ei+1ei \to e_{i+1}ei→ei+1​ and em→s1em \to s1em→s1, the answer is (n−1)+(m−1)+1(n-1) + (m-1) + 1(n−1)+(m−1)+1, but it is not the optimal choice;

The correct approach involves the notion of Bipartite-Graph as mentions above.

A DAG GGG, corresponds to a Bipartite-Graph BBB where L=(s1,s2,...,sn),R=(e1,...,em)L = (s1,s2,...,sn), R = (e1,...,em)L=(s1,s2,...,sn),R=(e1,...,em) where LLL is the set of points whose din=0din = 0din=0 and RRR for dout=0dout = 0dout=0, if sisisi can reach to ejejej then there is a edge si→ejsi \to ejsi→ej in BBB; It is obvious that BBB is also a DAG; There is a very crucial property on of this Partite: any point must has a edge (there exists a edge si→?si \to ?si→? or ?→ei? \to ei?→ei, ∀si,ej\forall si, ej∀si,ej)
Our goal is to make BBB becomes a SCC;
The whole process is:
Originally, GGG is DAG with BBB as its Bipartite, so we have ∣L∣>0,∣R∣>0|L| >0, |R| > 0∣L∣>0,∣R∣>0;
1 If min(∣L∣,∣R∣)≥2min( |L|, |R| ) \geq 2min(∣L∣,∣R∣)≥2, then there must exists at least two matches on BBB;
. Disproof: let l1,l2,r1,r2l1,l2, r1,r2l1,l2,r1,r2, if the maximal-match is 111, e.g., the only match is l1−r1l1-r1l1−r1, then all li→r1li \to r1li→r1 (if not, li−rili - rili−ri is another match); let’s consider the r2r2r2, if l1−r2l1-r2l1−r2 then l1−r2,l2−r1l1-r2, l2-r1l1−r2,l2−r1 is valid; otherwise li−r2li-r2li−r2 then l1−r1,li−r2l1-r1, li-r2l1−r1,li−r2 is also valid. Therefore, there must has at least 222 matches.
. we choose 222 matches, e.g., l1−r1,l2−r2l1-r1, l2-r2l1−r1,l2−r2, Add a new edge r1→l2r1 \to l2r1→l2; now r1,l2r1, l2r1,l2 is no longer Source or End, so we need remove them from BBB; Operation: 1 remove r1, l2 from BBB 2 Add new edges to BBB (add edge li→rjli \to rjli→rj if li→r1∧l2→rjli \to r1 \land l2 \to rjli→r1∧l2→rj) In fact, the new BBB is the Bipartite of the graph (maybe not DAG) (V,E+(r1→l2)(V, E + (r1 \to l2)(V,E+(r1→l2); the new BBB also has the property: any points has at least one edge; so continue this process until min(∣L∣,∣R∣)<2min( |L|, |R|) < 2min(∣L∣,∣R∣)<2;
2 Now, min(∣L∣,∣R∣)=1min( |L|, |R|) = 1min(∣L∣,∣R∣)=1 (it is impossible that it equals 000, cuz each process above will cause min(∣L∣,∣R∣)−1min( |L|, |R|) - 1min(∣L∣,∣R∣)−1; if ∣L∣=1|L| = 1∣L∣=1, for the property of BBB we have that there have edges l1→ri∀ril1 \to ri \quad \forall ril1→ri∀ri, so we add edge ri→ri+1ri \to r_{i+1}ri→ri+1​ and rn→l1rn \to l1rn→l1 (the similar device for the case ∣R∣=1|R| = 1∣R∣=1), then BBB would become a SCC; that is, add max(L,R)max( L, R)max(L,R) edges;

Therefore, the total count is: let kkk be the count of process 1 (add kkk edges, and causes ∣L∣,∣R∣|L|, |R|∣L∣,∣R∣ minus kkk), at 2 we will add max(L−k,R−k)max( L - k, R - k)max(L−k,R−k) edges, so max(L−k,R−k)+k=max(L,R)max( L - k, R - k) + k = max( L, R)max(L−k,R−k)+k=max(L,R)

Pseudocode:

Add_answer( int a, int b); //< add a new edge (a -> b) on G, it would be called `max(n, m)` times.G; //< DAG with Source (s1,...,sn), End (e1,...,em)
B; //< The Bipartite-Graph of `G`
L = {s1, ..., sn}; //< The left-set of `B`
R = {e1, ..., em}; //< The right-set of `B`
for( si){for( ej){if( si can reach to ej){B.add_edge( si, ej);}}
}int l = n, r = m;
while( min( l, r) >= 2){find two matches (denoted `l1-r1, l2-r2`);Add_answer( r1, l2);for( li : L){for( rj : R){if( there is a edge `li -> r1` && `l2 -> rj){B.add_edge( li, rj);}}remove `l1,r2` from `B`;remove `l1` from `L`, remove `r2` from `R`;-- l, -- r;
}// now, min(l, r) = 1
if( l <= r){for( int i = 0; i + 1 < r; ++i){Add_answer( R[i], R[i+1]);}Add_answer( R[r-1], L[0]);
}
else{for( int i = 0; i + 1 < l; ++i){Add_answer( L[i+1], L[i]);}Add_answer( R[0], L[0]);
}

@Delimiter

A Wrong Understanding

A wrong-understanding of the above idea is, let the maximal-match of BBB is kkk, l1−r1,...,lk−rkl1-r1, ..., lk-rkl1−r1,...,lk−rk, so there left (n−k)+(m−k)(n-k) + (m-k)(n−k)+(m−k) unmatched. Therefore, we connect k−1k-1k−1 edges ri→li+1ri \to l_{i+1}ri→li+1​, and (n−k)+(m−k)+1(n-k) +(m-k) +1(n−k)+(m−k)+1 edges rk→...→l1rk \to ... \to l1rk→...→l1;

This is wrong, e.g., G=(l1−r1)(l2−r1)(l3−r2)(l3−r3)G = (l1-r1) (l2-r1) (l3-r2) (l3-r3)G=(l1−r1)(l2−r1)(l3−r2)(l3−r3) (its Bipartite-Graph BBB is the same as GGG), the maximal-match is 222, let it be (l1−r1)(l3−r2)(l1-r1) (l3-r2)(l1−r1)(l3−r2), and l2,r3l2, r3l2,r3 are unmatched, then we add edge r1→l3r1 \to l3r1→l3 and r2→l2→r3→l1r2 \to l2 \to r3 \to l1r2→l2→r3→l1 (444 edges in total), surely it also becomes a SCC, but this is not the optimal choice (e.g., r2→l1,r3→l2,r1→l3r2\to l1, r3\to l2, r1 \to l3r2→l1,r3→l2,r1→l3 is also a SCC with 333 edges)

The correct construction-process based on the idea discussed above is,
1 Firstly, we choose two matches (l1−r1)(l3−r2)(l1-r1) (l3-r2)(l1−r1)(l3−r2) of BBB, add a edge r1→l3r1 \to l3r1→l3, subsequently r1,l3r1, l3r1,l3 are no longer the Source/End-Points in the new G1=G+(r1→l3)G1 = G + (r1 \to l3)G1=G+(r1→l3), the new Bipartite-Graph B1B1B1 of the new graph G1G1G1 becomes (l1−r2)(l1−r3)(l2−r2)(l2−r3)(l1-r2) (l1-r3) (l2-r2) (l2-r3)(l1−r2)(l1−r3)(l2−r2)(l2−r3)
2 Secondly, choose two matches (l1−r2)(l2−r3)(l1-r2) (l2-r3)(l1−r2)(l2−r3) of BBB, add a edge r2→l2r2 \to l2r2→l2, the new B2B2B2 of the new graph G2=G1+(r2→l2)G2 = G1 + (r2 \to l2)G2=G1+(r2→l2) becomes l1−r3l1-r3l1−r3
3 Finally, the understanding here is vital. the current BBB is l1−r3l1-r3l1−r3, what does it means? There are only one Source in current GGG, one End; let’s see the current-graph G:(l1)→(SCC)→(r3)G: (l1) \to (SCC) \to (r3)G:(l1)→(SCC)→(r3) where SCC=(l2,l3,r1,r2)SCC = (l2,l3,r1,r2)SCC=(l2,l3,r1,r2), in other words, once we make BBB a SCC, then GGG is also a SCC; Therefore, we add r3→l1r3 \to l1r3→l1 to make BBB a SCC;

One Tips:
At any step, every Closed-Sub-Graphs (Weakly-Connected) of GiGiGi, must has at least oneoneone Sources and Ends;
e.g., a Closed-Sub-Graph in GiGiGi would not be (l1→r1)(r1→l2)(l2→r1)(l1 \to r1) (r1 \to l2) (l2 \to r1)(l1→r1)(r1→l2)(l2→r1) which has 111 Source while 000 End. This case would never happened. Cuz each time we added a edge ri→ljri \to ljri→lj, it means there are li→rili \to rili→ri and lj→rjlj \to rjlj→rj, so in the new Closed-Sub-Graph (after add the new edge) which contains this new edge, it would still contains lilili as its Source and rjrjrj as its End.

`Computer-Algorithm` 有向无环图DAG相关推荐

  1. 后端 绘制有向无环图(DAG图)

    因为公司的某个系统比较古老,里面的 job 的管理几乎都是直接通过操作数据库来实现的,对于一般的操作还可以忍受,但是每次想知道 job 之间的依赖关系的时候,就会相当难受,于是便脑袋很抽地一定要写一个 ...

  2. 数据驱动应用(三):异构数据服务(基于有向无环图DAG)

    概述 主要概念 数据服务(Data Service):对异构数据源,基于有向无环图,提供异构数据的查询和推送能力. 指标:用于衡量事物发展程度的单位或方法,它还有个IT上常用的名字,也就是度量.例如: ...

  3. Apache Spark中的有向无环图DAG

    Apache Spark中的有向无环图DAG 由DATAFLAIR TEAM ·更新· 2018年11月21日 1.目的 在本Apache Spark教程中,我们将了解Apache Spark中的DA ...

  4. 大数据工作流任务调度--有向无环图(DAG)之拓扑排序

    拓扑排序(Topological Sorting) 回顾基础知识: 1.图的遍历: 图的遍历是指从图中的某一个顶点出发,按照某种搜索方法沿着图中的边对图中的所有顶点访问一次且仅访问一次.注意树是一种特 ...

  5. 有向无环图DAG 拓扑排序 代码解释

    目录: DAG定义 举例描述 实际运用 算法描述 算法实战 算法可视化 定义 在图论中,由一个有向无环图的顶点组成的序列,当且仅当满足下列条件时,称为该图的一个拓扑排序(英语:Topological ...

  6. C#实现有向无环图(DAG)拓扑排序

    对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在 ...

  7. 有向无环图(DAG)拓扑排序的两种方法

    如下图的DAG: 第一种: (1)从AOV网中选择一个没有前驱的顶点并且输出它: (2)从AOV网中删除该顶点,并且上去所有该顶点为尾的弧: (3)重复上述两步,直到全部顶点都被输出,或者AOV网中不 ...

  8. java 有向无环图 树_拓扑排序-有向无环图(DAG, Directed Acyclic Graph)

    条件: 1.每个顶点出现且只出现一次. 2.若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面. 有向无环图(DAG)才有拓扑排序,非DAG图没有拓扑排序一说. 一 ...

  9. 有向无环图(DAG)的温故知新

    当我们学习数据结构的时候,总是觉得很枯燥,而当我们解决实际问题的时候,又往往因为对数据结构了解的匮乏而束手无策.从问题中来,到问题中去,在某一点上的深入思考并且不断的实践积累,或许是个笨办法,但笨办法 ...

最新文章

  1. mysql 5.6 uf8mb4_MySQL5.7升级到8.0过程详解
  2. 读“基于机器学习的无参考图像质量评估综述”有感
  3. Comparative assessment of long-read error correction software applied to Nanopore RNA-sequencing dat
  4. zset中的score_每天五分钟,成就redis大神之Zset数据类型
  5. 生成allure测试报告时报错的解决方法
  6. [YTU]_2633( P3 数钱是件愉快的事)
  7. python 银行工作_Python:银行系统实战(一)
  8. 指标波动多大才算是异常?
  9. 收款码合并有什么弊端_为什么明明有个人收款码了,还要申请微信收款商业版?...
  10. 暑假周进度总结报告5
  11. html图片上传阅览并且点击放大
  12. 学hadoop需要什么基础
  13. OpenSSL之PKey的EVP封装
  14. 在Visio里加上、下标方法
  15. 适合记录日常工作的便签如何在电脑桌面上添加
  16. GitHub账户注册流程及常见问题解析
  17. django批量修改table_django formset实现数据表的批量操作的示例代码
  18. 力扣第十五题-三数之和
  19. 【分享】Xmind会默认安装在C盘,如何将Xmind安装在指定文件夹
  20. 数据库触发器实例讲解

热门文章

  1. 数据库的完全依赖,部分依赖和传递依赖
  2. Vue-demo兄弟组件如何传值
  3. 黑鹰的学习网站--感兴趣的可以去看看
  4. 前沿 | 中国中小银行都是如何展开数字化转型的?
  5. vue3+h5实现手写签名
  6. 光模块MSA多源协议详细解析
  7. Python爬虫入门 | 5 爬取小猪短租租房信息
  8. 关于如何正确安装python的一些资源包和库的操作命令
  9. 词根词缀学单词【3】
  10. 先打基础,再赶时髦:摆弄新工具之前,先把手艺学好