Graphe biparti

Un graphe est dit biparti si on peut colorer ses sommets avec uniquement deux couleurs de telle manière que deux sommets voisins quelconques n'ont pas la même couleur.

Le graphe ci-dessous est biparti.

graph LR
    n00((0)) --- n10((1))
    n00 --- n20((2))
    n00 --- n30((3))
    n10 --- n40((4))
    n30 --- n50((5))
    n30 --- n60((6))
    n30 --- n70((7))
    n70 --- n10
    n40 --- n20
    n60 --- n10
    n80((8)) --- n50
    n80 --- n40
Coloration

Les sommets sont colorés avec uniquement deux couleurs. Aucun sommet n'a un voisin de la même couleur.

graph LR
    classDef jaune fill:#ff0, color:#38474f;
    classDef bleu fill:#0ff, color:#38474f;
    n0((0)) --- n1((1))
    class n0 jaune
    class n1 bleu
    n0 --- n2((2))
    class n2 bleu
    n0 --- n3((3))
    class n3 bleu
    n1 --- n4((4))
    class n4 jaune
    n3 --- n5((5))
    class n5 jaune
    n3 --- n6((6))
    class n6 jaune
    n3 --- n7((7))
    class n7 jaune
    n7 --- n1
    n4 --- n2
    n6 --- n1
    n8((8)) --- n5
    class n8 bleu
    n8 --- n4

Séparation

Le même graphe dessiné avec les sommets regroupés par couleur.

graph TD
    %% défintions
    n0((0))
    n4((4))
    n5((5))
    n6((6))
    n7((7))
    n1((1))
    n3((3))
    n2((2))
    n8((8))

    %% sous-gaphes
    subgraph SG1 [" "]
    n0
    n4
    n6
    n7
    n5
    end

    subgraph SG2 [" "]
    n2
    n1
    n3
    n8
    end

    %% arêtes
    n1 --- n0
    n3 --- n0
    n2 --- n0
    n1 --- n4
    n2 --- n4
    n3 --- n5
    n3 --- n6
    n3 --- n7
    n1 --- n6
    n8 --- n5
    n1 --- n7
    n8 --- n4

    %% classes
    classDef jaune fill:#ff0, color:#38474f;
    classDef bleu fill:#0ff, color:#38474f;
    classDef jaune-pale fill:#ffff0018, stroke:#ffff00;
    classDef bleu-pale fill:#00ffff18, stroke:#00ffff;
    class n4 jaune
    class n5 jaune
    class n6 jaune
    class n7 jaune
    class n0 jaune
    class n2 bleu
    class n3 bleu
    class n1 bleu
    class n8 bleu
    class SG1 jaune-pale;
    class SG2 bleu-pale;

Cette observation illustre une autre définition des graphes bipartis :

« On considère un graphe connexe non orienté \(G(S, A)\). \(S\) est l'ensemble des sommets, \(A\) l'ensemble des arêtes. Ce graphe est dit biparti si l'ensemble \(S\) peut être divisé en deux sous-ensembles disjoints \(S_1\) et \(S_2\) tels que chaque arête de \(A\) a une extrémité dans \(S_1\) et l'autre extrémité dans \(S_2\). »

Un graphe est implémenté à l'aide d'un dictionnaire. Un sommet est représenté par son numéro. Les clés du dictionnaire sont les sommets. La valeur associée à une clé s est la liste des voisins du sommet s. Par exemple, le graphe plus haut est représenté par: {0: [1, 2, 3], 1: [0, 4, 6, 7], 2: [0, 4], ...}.

Compléter la fonction est_biparti qui prend en paramètres un graphe graphe supposé connexe et un sommet sommet_initial à partir duquel le parcours est effectué et renvoie True si le graphe est biparti et False sinon. Un tableau couleurs servira à stocker à chaque indice i la couleur du sommet numéro i (voir plus bas).

Algorithme

On utilise une file et un parcours en largeur.

On affecte au premier sommet la couleur \(1\), puis à ses voisins la couleur \(-1\). On parcourt ensuite les voisins des voisins qui n'ont pas déjà été colorés en leur affectant la couleur \(1\), et ainsi de suite.

Si, lorsqu'on explore les voisins d'un sommet s, on en rencontre un qui est déjà coloré, soit sa couleur est différente de celle de s et on ne fait rien, soit sa couleur est identique à celle de s et alors le graphe n'est pas biparti.

Les sommets sont visités dans un parcours en largeur implémenté à l'aide d'une file.

Colorer le sommet initial et le placer dans la file

Tant que le file n'est pas vide :

Défiler un sommet Visiter chacun de ses voisins :

Si un voisin n'est pas coloré, lui donner une couleur et le placer dans la file
Sinon, contrôler sa couleur et renvoyer éventuellement False

Renvoyer True si le parcours est terminé

Aide: utilisation de deque pour implémenter une file

On crée une file vide avec l'instruction file = deque(). Pour insérer un élément elt dans la file, on écrit file.append(elt). Pour défiler un élément et l'affecter, on écrit elt = file.popleft(). La fonction len renvoie la longueur de la file.

Exemples
1
2
3
4
5
6
>>> g = {0: [1, 2], 1: [0, 2], 2: [0, 1]}
>>> est_biparti(g, 0)
False
>>> g = {0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]}
>>> est_biparti(g, 0)
True

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 5/5

.128013pFvhkugSêef1éw y0[s(;d93/.:i,l4P)T=obO56ancrtI_xDè2Rq]m-78050w0k0T0P0C0E0t0p0R0E0P0t0t0J010T0C0b010406050t0g0%0%0P0S0q040i0K0E0g0~0K0Q0p020P0%0b0v0p0!0k180S0#0g0k0t050z1517191b130b04051G1z1J0z1G130w0C0d0?0^0`0|0^0Q0h0g0P0h0k0(0b0q0T0e1i0p0e0C0h0e0E1/0e0T11050.0L0E0k1S0_0{011.1:1=1:0T1{1}1_0T0S1H1*0?1e0t0b0P0Q0|0Z011 1U010l0:0k0Q1m0k1_2h2j2o212r1}2u0%2w040a0p0G0S0K0b0K0t0C1h1j0,2f0S0S0k0R2R1z2y0Q1H0z1*2%2b2d2c1`0w2A1V0C0Q2t2O1_1P1R0@202;2?0Q0K2`1_0b2W1H2#2%37142i1j2|2p300S180E1_0P1-2W0l0|030V0V0R310k1=2 0K0(0m3y110p0m1z0P383b123a2z3d213f3h3j3l0k3n013p3r3t3v2@3y0(2m040p0Z3E3G2j3I2#2:013N0P3i1H3k0e3m3o3q3s0,3X303Z0y3B0y3)2!3H133-3L0|3:3=053@3_3T3{3W2=3Y3z0F3B0F441A463J3c1T3M0K3g3;3P3^3R3`3V3}4j3 3z0N3B0N4p37473b3.4b4z4f3U3|3u4F3x3z0O3B0O4L4r484u4a4w3O3?3Q3S4T4i3w3Z0)3B0)4$3+4N3K4)3/4+4y4-4A4/4h4E4=3z0*3B0*4`2$4|4t2}4 4x4c4e4B4g4D4V570(0x3B0x5c3,4O495h4,4d4.4C4U3~4X3y0r110m0r5u5e4P505j5B5m5D4W3Z0m0m5I3D0z3F454{4s5N5i4R5l4:564k3y3#0m3(5Z3*5d5%5x4Q524S555o5.0m4104615L5_4~5{5A535C4;604m634o5?5#5^4(5g685k545n5E5U4I634K6h4q5$6k3e5O5*6o5S5p0m4Z634#6v391M351z2`2*0w2d2/5x4U2_1Q1H340k363H6i1H4U6!2z0C0w0|3q2#5U3P6+6-6p5T3z5W0p2E0k6?6D601_6h6y210f0Q110l2L0%6$665g0o3B7b734a76043s0E1}2Y0C1i1y6w2$7c2p7e3$7g5w4~75110C1n4w0T6$0p7u3M110,1v0k6$137s6)1j6=016.3b3Z3#5A7U5~6q3z2m6{2v6~6c4G3!713F7Q393-7#0V6/3z627!6,7V6@5p417*2F7,5-7.7|727z5g0f7L3R7y4}7d7f7R7J4a0l111x0T0V0L0 190~8f5f2p10040u8v4P110h0S0P0b0e7O8j7h018y0D7H8k3/110t0K170-0V2=2Q0C3;8B5x8y0H0B7P8B7^7`0(6e7}855 7.4m836}7 6 8@7:3$0p908Q7j3s0g1}0g0S7r377I8L0K110J8P8L8y0s8$4~0%0C115K7R9b8a2p8c040l4w9g9s7K04993H9r8g2p0K7w2=9y9F9A8E8G8I9k5g8y0$8+8K4O8-7X4H6;7~7$6^0(4I8_8=7%9(8~90918L930K950k979C3+8Q9i9Q3e8S8U2F8p8Y0~8#9V9L0|9S9K8w219d049f9q8Q9m5I9U7?9W9#7_9Y0(6G8;8{7-5F4Z9*au86aw9.9/92772sab3.aeag9aaE047M1w9~218y0u0Hal6#7@ao8.4@4-7^8|5F4@ay9$5pa!3)9/9Eac4aaF1}aQ0|ae0Aa^8R048G0b2t0wa|aSa|7j8T8Va30Q8Za6ama88M11aU7R7=aWan6?8.59a#aoa%3Z59a*805.boa.aD8L9u0o1.a@ah9;0L112Db3118Aa7a;a}2C8JbdbO8(aH5xae020h0T0vbV9l9n049pbS3.8y8*bi8,aYaq5rbp9+9%5rbubr3zb?bya/9:9za=9Ba10-b$5gaJc79 9vaGbNaI11a{ce5`112N0b1}0l7Gci4~aSbh4Mb:bmaq5J9!b^6E5Hb{av5U5H2%3Fc0bzc2019u9w0Sca9A0d0K0C2P0QcQa_9IcWbFcL7j9N8HbRbkbe9}cq6la0b8bK040$b.cuce9X2j5U5Wb@az8?5F5V2n6|cA60c~b cJcKbe9u0C0lcXa}949698c=9jc.cbcScU9JdnaR119Tc#beaJaK9Daib(b*c+bT11c^4rc`b;c|6_7Z3ka$cEdMd47+d09,5;aCdadaaMdi9^dkdsa911dmb+cj04dpcVc=dvaL9c9edgae0(dg9=9@9_dlb5c:a2d;aV9{aXcwdL3y7|dObqdQeadS84dU9%61dXdYc0aMbQa|a`e1a~0bb00Qb2d(bf8zesd/drd,crbge57te77 8.0m8:ecd67.eMeg8`a+6deldY8Q9u4VdfdwbOd}dj9`eIcLc-eEc/d.cTd:eyaae$cfafdz3+a:8C7k9?e)e0eyb6c5cpe.8xdudH5$dJe80Q6rczei6E9)d5fh606sd9emdbbO9u2W0T97c!d?cL0f0R110c3;0tc*fbb+c{fe6_aseOfleQaxfkeUfOeleY11ftfvdgfz110I0SaPb/8j0z6(1K6M0z6O1z0T6Qf:2-2(0P1|6Z6N6W1F7S3.2W0%0V0l0P0f0k0V0e621r1t7N0=fa7t1M3I1G0X2j0=1}0?0_0p0w000g1jc(8I6{1,3s0Q2?0W0k0D0p1,1g0:cU0k8F2Q0?0-0T1~9w0Q7o1,0P0d2X0?0e0P7N2f7E0t2jgP2fgA0kgC0p2N970p0d0n0Sde0CgK0p2PgY0P0Rgt1~gr3u1}0=8o0p8r2i0S0~1~9?g/0_ch1N1I040M1jb01g0pg1197N0S0p1vgsgu8Fc)h88shb0C6{1~2N0`0Y2T0P0gh03c0q0@1~7D2i0C0Shhgi040U0E0p0q0p3k0n1v1Q3;2t0R1~2t2b1~h5gq9^0Wg/2L340C0n0T0n0t0B0p010jh:hAha0~2n0-i22?g/2O0t0n0,hthKhM0?hOgnhR0/0S01hV7Q0,0.0:0t04.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 5/5

.128013pFvhkugSêef1éw y0[s(;d93/.:i,l4P)T=obO56ancrtI_xDè2Rq]m-78050w0k0T0P0C0E0t0p0R0E0P0t0t0J010T0C0b010406050t0g0%0%0P0S0q040i0K0E0g0~0K0Q0p020P0%0b0v0p0!0k180S0#0g0k0t050z1517191b130b04051G1z1J0z1G130w0C0d0?0^0`0|0^0Q0h0g0P0h0k0(0b0q0T0e1i0p0e0C0h0e0E1/0e0T11050.0L0E0k1S0_0{011.1:1=1:0T1{1}1_0T0S1H1*0?1e0t0b0P0Q0|0Z011 1U010l0:0k0Q1m0k1_2h2j2o212r1}2u0%2w040a0p0G0S0K0b0K0t0C1h1j0,2f0S0S0k0R2R1z2y0Q1H0z1*2%2b2d2c1`0w2A1V0C0Q2t2O1_1P1R0@202;2?0Q0K2`1_0b2W1H2#2%37142i1j2|2p300S180E1_0P1-2W0l0|030V0V0R310k1=2 0K0(0Z0(0m110p0m1z0P383b123a2z3d213f3h3j3l0k3n013p3r3t3v2@3y3y3C0Z3F3H2j3J2#2:013O0P3i1H3k0e3m3o3q3s0,3Y303!0y3C0y3(2!3I133,3M0|3/3;053?3^3U3`3X2=3Z3z0F3C0F431A453K3c1T3N0K3g3:3Q3@3S3_3W3|4i3~3z0N3C0N4o37463b3-4a4y4e3V3{3u4E3x3z0O3C0O4K4q474t494v3P3=3R3T4S4h3w3!0)3C0)4#3*4M3L4(3.4*4x4,4z4.4g4D4;3z0*3C0*4_2$4{4s2}4~4w4b4d4A4f4C4U560(0x3C0x5b3+4N485g4+4c4-4B4T3}4W3A0r110m0r5t5d4O4 5i5A5l5C4V3!0m3B045U5K4r5M5h4Q5k4/554j3A2m5W3%0z3G444`5Z5w4P514R545n5*0m405W425/3)5c5?4}5^5z525B4:5}4l5W4n625;644%5f675j535m5D5T4H5W4J6g4p5=6j3e5N5$6n5R5o0m4Y5W4!6u391M351z2`2*0w2d2/5w4T2_1Q1H340k363I6h1H4T6Z2z0C0w0|3q2#5T3Q6*6,6o5S3z3B0p2E0k6=6C5}1_6g6x210f0Q110l2L0%6#655f0o3C7a724975043s0E1}2Y0C1i1y6v2$7b2p7d040p7f5v4}74110C1n4v0T6#7x7g3.110,1v0k6#137r6(1j6;016-3b3!5,5z7U5{6p3z2m6`2v6}6b4F3#2%3G7Q393,7#0V6.3z5 7!6+7V6?5o407*2F7,5)7.7|717z5f0f7L3S7y4|7c7e7R7t3N0l111x0T0V0L0 190~8f5e2p10040u8v4O110h0S0P0b0e7O8j7J8y0D7H8k49110t0K170-0V2=2Q0C3:8B5w8y0H0B7P8B7^7`0(6d7}855|7.4l836|7 6~8?703G0p8 7I8a3e113s0g1}0g0S7q37918g2p0K110J8O8L110s8#4}0%0C115J7R9c8w73764v9i923N8R9y9d210K7v2=9C9u8Q048E8G8I9m5f8y0$8*8K4N8,7X4G6:7~7$6@0(4H8^8;7%9%8}7w908P7K7j0K960k989a6!9j049l9U9D9K8S8U8p8X0~8!9 9J019R9I3-9f049h9s9:9o5H9T7?9V9!7_9X0(6F8:8`7-5E4Y9)au86aw9-909t8C042C8J9b9:aeagaJ7J7i7M1w9P8x110u0Hal9{an6=8-4?4,7^8{5E4?ay9#5oa$3(aD9:7iaHaS9E110Aa^9K8G0b2t0wa|aaaUb27ia22Fa40Q8Ya7ama0b304aW7R7=aY6)ao8-58a%aoa)3!58a,805*boa:9/7J8c040o1.1}ac5@0L112Db28y8Aa8aFa@bO8$11bhaN9z0|ae020h0T0vbG9n9p049rbda98y8)bi8+bmaq5qbp9*9$5qbubr3zb@byaD8 a=8R8Tb8b%5faLc793aG2sb2aea{bR66112N0b1}0l7Gch9QaUbU4qbO9W2j5T5Gb^az8=5E5I2n6{b_6Dcyc0c19:bB0l9xahaO110d0K0C2P0Qca9E9GcWcPbW9;9M8HaIbkb-9kb5c4a3bL110$b/4Lb;a!aq5U9ZcG5}6_cFcA9+c|7:9.c1cKbA7C0lcX9K959799c;9}c.04cScU9HcpaT049Sc#beaLaM3IaE5wajb*dhc@ctb,0pcv0Q5T7Z3ka(avdIcE7+d29$0m7Z62d7dVbzc$7ide9^dgdo218y9~dE5@cRcTcVdhdrbVdt9gdc01ae0(d^dZ9?df9`3*9:d)djb70-d:aXe17@b=cw6^7|dKbqdMeddO84dQ6D888~dWdVc3ccbFd%bXa`dja~b0dhbNd+cidkd.dneCcqbge87seac`ec3A8/efc~7.0m8@d1a-6caCepc2d9044Udbdsa9d}9@9_dhd*c+aFdld/eubfd;dwaK9gdv3*dxeDd!e.e^e3e^b6c5e6f4c=dC5=cuebdH6^6rateXeT9(eWbvfleZe!a;e$2W0T98c!d=a90f0R110c3:0tc*fddEdG5TaseRel5}axfnb}3AasdUdXbebBfufwd^fA110I0SaRb:8j0z6%1K6L0z6N1z0T6Pf=2-2(0P1|6Y6M6V1F7S3-2W0%0V0l0P0f0k0V0e5 1r1t7N0=fc7s1M3J1G0X2j0=1}0?0_0p0w000g1jc(8I6`1,3s0Q2?0W0k0D0p1,1g0:cU0k8F2Q0?0-0T1~cN0Q7n1,0P0d2X0?0e0P7N2f7E0t2jgR2fgC0kgE0p2N980p0d0n0S0C2rgM0p2Pg!0P0Rgv1~gt3u1}0=8o0p8r2i0S0~1~9?g;0_cg1N1I040M1ja 1g0pg3197N0S0p1vgugw8Fc)ha8shd0C6`1~2N0`0Y2T0P0gh23c0q0@1~7D2i0C0Shjgk040U0E0p0q0p3k0n1v1Q3:2t0R1~2t2b1~h7gs9^0Wg;2L340C0n0T0n0t0B0p010jh=hChc0~2n0-i42?g;2O0t0n0,hvhMhO0?hQgphT0/0S01hX7Q0,0.0:0t04.