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

.128013oèPf8gbr1a3tv=un9xsc)7qR/p0OdI; lk5:,Fy2éhwT6e[(S]_iêm.4D-050D0U0m0k0!0H0t0G0u0H0k0t0t0o010m0!0A010406050t0p0$0$0k0i0N040X0b0H0p0~0b0q0G020k0$0A0F0G0y0U180i0x0p0U0t050z1517191b130A04051G1z1J0z1G130D0!0n0?0^0`0|0^0q0g0p0k0g0U0*0A0N0m0Q1i0G0Q0!0g0Q0H1/0Q0m11050.0h0H0U1S0_0{011.1:1=1:0m1{1}1_0m0i1H1*0?1e0t0A0k0q0|0O011 1U010e0:0U0q1m0U1_2h2j2o212r1}2u0$2w040a0G0d0i0b0A0b0t0!1h1j0,2f0i0i0U0u2R1z2y0q1H0z1*2%2b2d2c1`0D2A1V0!0q2t2O1_1P1R0@202;2?0q0b2`1_0A2W1H2#2%37142i1j2|2p300i180H1_0k1-2W0e0|030Z0Z0u310U1=2 0b0*0j3y110G0j1z0k383b123a2z3d213f3h3j3l0U3n013p3r3t3v2@3y0*2m040G0O3E3G2j3I2#2:013N0k3i1H3k0Q3m3o3q3s0,3X303Z0l3B0l3)2!3H133-3L0|3:3=053@3_3T3{3W2=3Y3z0(3B0(441A463J3c1T3M0b3g3;3P3^3R3`3V3}4j3 3z0J3B0J4p37473b3.4b4z4f3U3|3u4F3x3z0T3B0T4L4r484u4a4w3O3?3Q3S4T4i3w3Z0w3B0w4$3+4N3K4)3/4+4y4-4A4/4h4E4=3z0f3B0f4`2$4|4t2}4 4x4c4e4B4g4D4V570*0r3B0r5c3,4O495h4,4d4.4C4U3~4X3y0B110j0B5u5e4P505j5B5m5D4W3Z0j0j5I3D0z3F454{4s5N5i4R5l4:564k3y3#0j3(5Z3*5d5%5x4Q524S555o5.0j4104615L5_4~5{5A535C4;604m634o5?5#5^4(5g685k545n5E5U4I634K6h4q5$6k3e5O5*6o5S5p0j4Z634#6v391M351z2`2*0D2d2/5x4U2_1Q1H340U363H6i1H4U6!2z0!0D0|3q2#5U3P6+6-6p5T3z5W0G2E0U6?6D601_6h6y210I0q110e2L0$6$665g0R3B7b734a76043s0H1}2Y0!1i1y6w2$7c2p7e3$7g5w4~75110!1n4w0m6$0G7u3M110,1v0U6$137s6)1j6=016.3b3Z3#5A7U5~6q3z2m6{2v6~6c4G3!713F7Q393-7#0Z6/3z627!6,7V6@5p417*2F7,5-7.7|727z5g0I7L3R7y4}7d7f7R7J4a0e111x0m0Z0h0 190~8f5f2p10040W8v4P110g0i0k0A0Q7O8j7h018y0L7H8k3/110t0b170-0Z2=2Q0!3;8B5x8y0v0K7P8B7^7`0*6e7}855 7.4m836}7 6 8@7:3$0G908Q7j3s0p1}0p0i7r377I8L0b110o8P8L8y0V8$4~0$0!115K7R9b8a2p8c040e4w9g9s7K04993H9r8g2p0b7w2=9y9F9A8E8G8I9k5g8y0Y8+8K4O8-7X4H6;7~7$6^0*4I8_8=7%9(8~90918L930b950U979C3+8Q9i9Q3e8S8U2F8p8Y0~8#9V9L0|9S9K8w219d049f9q8Q9m5I9U7?9W9#7_9Y0*6G8;8{7-5F4Z9*au86aw9.9/92772sab3.aeag9aaE047M1w9~218y0W0val6#7@ao8.4@4-7^8|5F4@ay9$5pa!3)9/9Eac4aaF1}aQ0|ae0%a^8R048G0A2t0Da|aSa|7j8T8Va30q8Za6ama88M11aU7R7=aWan6?8.59a#aoa%3Z59a*805.boa.aD8L9u0R1.a@ah9;0h112Db3118Aa7a;a}2C8JbdbO8(aH5xae020g0m0FbV9l9n049pbS3.8y8*bi8,aYaq5rbp9+9%5rbubr3zb?bya/9:9za=9Ba10-b$5gaJc79 9vaGbNaI11a{ce5`112N0A1}0e7Gci4~aSbh4Mb:bmaq5J9!b^6E5Hb{av5U5H2%3Fc0bzc2019u9w0ica9A0n0b0!2P0qcQa_9IcWbFcL7j9N8HbRbkbe9}cq6la0b8bK040Yb.cuce9X2j5U5Wb@az8?5F5V2n6|cA60c~b cJcKbe9u0!0ecXa}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~0Ab00qb2d(bf8zesd/drd,crbge57te77 8.0j8:ecd67.eMeg8`a+6deldY8Q9u4VdfdwbOd}dj9`eIcLc-eEc/d.cTd:eyaae$cfafdz3+a:8C7k9?e)e0eyb6c5cpe.8xdudH5$dJe80q6rczei6E9)d5fh606sd9emdbbO9u2W0m97c!d?cL0I0u110M3;0tc*fbb+c{fe6_aseOfleQaxfkeUfOeleY11ftfvdgfz110S0iaPb/8j0z6(1K6M0z6O1z0m6Qf:2-2(0k1|6Z6N6W1F7S3.2W0$0Z0e0k0I0U0Z0Q621r1t7N0=fa7t1M3I1G0)2j0=1}0?0_0G0D000p1jc(8I6{1,3s0q2?0s0U0L0G1,1g0:cU0U8F2Q0?0-0m1~9w0q7o1,0k0n2X0?0Q0k7N2f7E0t2jgP2fgA0UgC0G2N970G0n0P0ide0!gK0G2PgY0k0ugt1~gr3u1}0=8o0G8r2i0i0~1~9?g/0_ch1N1I040C1jb01g0Gg1197N0i0G1vgsgu8Fc)h88shb0!6{1~2N0`0c2T0k0ph03c0N0@1~7D2i0!0ihhgi040E0H0G0N0G3k0P1v1Q3;2t0u1~2t2b1~h5gq9^0sg/2L340!0P0m0P0t0K0G010#h:hAha0~2n0-i22?g/2O0t0P0,hthKhM0?hOgnhR0/0i01hV7Q0,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

.128013oèPf8gbr1a3tv=un9xsc)7qR/p0OdI; lk5:,Fy2éhwT6e[(S]_iêm.4D-050D0U0m0k0!0H0t0G0u0H0k0t0t0o010m0!0A010406050t0p0$0$0k0i0N040X0b0H0p0~0b0q0G020k0$0A0F0G0y0U180i0x0p0U0t050z1517191b130A04051G1z1J0z1G130D0!0n0?0^0`0|0^0q0g0p0k0g0U0*0A0N0m0Q1i0G0Q0!0g0Q0H1/0Q0m11050.0h0H0U1S0_0{011.1:1=1:0m1{1}1_0m0i1H1*0?1e0t0A0k0q0|0O011 1U010e0:0U0q1m0U1_2h2j2o212r1}2u0$2w040a0G0d0i0b0A0b0t0!1h1j0,2f0i0i0U0u2R1z2y0q1H0z1*2%2b2d2c1`0D2A1V0!0q2t2O1_1P1R0@202;2?0q0b2`1_0A2W1H2#2%37142i1j2|2p300i180H1_0k1-2W0e0|030Z0Z0u310U1=2 0b0*0O0*0j110G0j1z0k383b123a2z3d213f3h3j3l0U3n013p3r3t3v2@3y3y3C0O3F3H2j3J2#2:013O0k3i1H3k0Q3m3o3q3s0,3Y303!0l3C0l3(2!3I133,3M0|3/3;053?3^3U3`3X2=3Z3z0(3C0(431A453K3c1T3N0b3g3:3Q3@3S3_3W3|4i3~3z0J3C0J4o37463b3-4a4y4e3V3{3u4E3x3z0T3C0T4K4q474t494v3P3=3R3T4S4h3w3!0w3C0w4#3*4M3L4(3.4*4x4,4z4.4g4D4;3z0f3C0f4_2$4{4s2}4~4w4b4d4A4f4C4U560*0r3C0r5b3+4N485g4+4c4-4B4T3}4W3A0B110j0B5t5d4O4 5i5A5l5C4V3!0j3B045U5K4r5M5h4Q5k4/554j3A2m5W3%0z3G444`5Z5w4P514R545n5*0j405W425/3)5c5?4}5^5z525B4:5}4l5W4n625;644%5f675j535m5D5T4H5W4J6g4p5=6j3e5N5$6n5R5o0j4Y5W4!6u391M351z2`2*0D2d2/5w4T2_1Q1H340U363I6h1H4T6Z2z0!0D0|3q2#5T3Q6*6,6o5S3z3B0G2E0U6=6C5}1_6g6x210I0q110e2L0$6#655f0R3C7a724975043s0H1}2Y0!1i1y6v2$7b2p7d040G7f5v4}74110!1n4v0m6#7x7g3.110,1v0U6#137r6(1j6;016-3b3!5,5z7U5{6p3z2m6`2v6}6b4F3#2%3G7Q393,7#0Z6.3z5 7!6+7V6?5o407*2F7,5)7.7|717z5f0I7L3S7y4|7c7e7R7t3N0e111x0m0Z0h0 190~8f5e2p10040W8v4O110g0i0k0A0Q7O8j7J8y0L7H8k49110t0b170-0Z2=2Q0!3:8B5w8y0v0K7P8B7^7`0*6d7}855|7.4l836|7 6~8?703G0G8 7I8a3e113s0p1}0p0i7q37918g2p0b110o8O8L110V8#4}0$0!115J7R9c8w73764v9i923N8R9y9d210b7v2=9C9u8Q048E8G8I9m5f8y0Y8*8K4N8,7X4G6:7~7$6@0*4H8^8;7%9%8}7w908P7K7j0b960U989a6!9j049l9U9D9K8S8U8p8X0~8!9 9J019R9I3-9f049h9s9:9o5H9T7?9V9!7_9X0*6F8:8`7-5E4Y9)au86aw9-909t8C042C8J9b9:aeagaJ7J7i7M1w9P8x110W0val9{an6=8-4?4,7^8{5E4?ay9#5oa$3(aD9:7iaHaS9E110%a^9K8G0A2t0Da|aaaUb27ia22Fa40q8Ya7ama0b304aW7R7=aY6)ao8-58a%aoa)3!58a,805*boa:9/7J8c040R1.1}ac5@0h112Db28y8Aa8aFa@bO8$11bhaN9z0|ae020g0m0FbG9n9p049rbda98y8)bi8+bmaq5qbp9*9$5qbubr3zb@byaD8 a=8R8Tb8b%5faLc793aG2sb2aea{bR66112N0A1}0e7Gch9QaUbU4qbO9W2j5T5Gb^az8=5E5I2n6{b_6Dcyc0c19:bB0e9xahaO110n0b0!2P0qca9E9GcWcPbW9;9M8HaIbkb-9kb5c4a3bL110Yb/4Lb;a!aq5U9ZcG5}6_cFcA9+c|7:9.c1cKbA7C0ecX9K959799c;9}c.04cScU9HcpaT049Sc#beaLaM3IaE5wajb*dhc@ctb,0Gcv0q5T7Z3ka(avdIcE7+d29$0j7Z62d7dVbzc$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.0j8@d1a-6caCepc2d9044Udbdsa9d}9@9_dhd*c+aFdld/eubfd;dwaK9gdv3*dxeDd!e.e^e3e^b6c5e6f4c=dC5=cuebdH6^6rateXeT9(eWbvfleZe!a;e$2W0m98c!d=a90I0u110M3:0tc*fddEdG5TaseRel5}axfnb}3AasdUdXbebBfufwd^fA110S0iaRb:8j0z6%1K6L0z6N1z0m6Pf=2-2(0k1|6Y6M6V1F7S3-2W0$0Z0e0k0I0U0Z0Q5 1r1t7N0=fc7s1M3J1G0)2j0=1}0?0_0G0D000p1jc(8I6`1,3s0q2?0s0U0L0G1,1g0:cU0U8F2Q0?0-0m1~cN0q7n1,0k0n2X0?0Q0k7N2f7E0t2jgR2fgC0UgE0G2N980G0n0P0i0!2rgM0G2Pg!0k0ugv1~gt3u1}0=8o0G8r2i0i0~1~9?g;0_cg1N1I040C1ja 1g0Gg3197N0i0G1vgugw8Fc)ha8shd0!6`1~2N0`0c2T0k0ph23c0N0@1~7D2i0!0ihjgk040E0H0G0N0G3k0P1v1Q3:2t0u1~2t2b1~h7gs9^0sg;2L340!0P0m0P0t0K0G010#h=hChc0~2n0-i42?g;2O0t0P0,hvhMhO0?hQgphT0/0i01hX7Q0,0.0:0t04.