#include <iostream> #include <cstdio> #include <algorithm> #include <vector> using namespace std; vector <int> graf[1000003]; string kolor_st; string kolor_do; int kolor_startowy[1000003]; int kolor_docelowy[1000003]; int moge[1000003]; int stany[1000003][2][3]; // [i][j][k] tyle razy synowie i wymagali skoczyc z j a mogli miec wartosc k int n; int nowy_korzen=-1; bool DFS(int q) { // cout<<"q="<<q<<" "; moge[q]=-2; for (int i=0; i<graf[q].size(); i++) { if (moge[graf[q][i]]==-1) DFS(graf[q][i]); else continue; int syn=graf[q][i]; //mamy juz przetworzone poddrzewo syn <=> w moge[] na pozycji syn jest dobra wartosc (0,1,2) stany[q][kolor_docelowy[syn]][moge[syn]]++; // cout<<"syn= "<<syn<<", stany["<<q<<"]["<<kolor_docelowy[syn]<<"]["<<moge[syn]<<"]="<<stany[q][kolor_docelowy[syn]][moge[syn]]<<"\n"; } // pamietamy, ze maja do dyspozycji tez moj kolor poczatkowy if (graf[q].size()==1 && q!=nowy_korzen) // jest lisciem to da sie zrobic synow liscia czyli nic { moge[n+1]=1; // informacja ze sie da poddrzewo moge[q]=kolor_startowy[q]; //informacja z jakim kolorem moge byc uzywajac tylko poddrzewa // cout<<"TU"; return true; } else { if (stany[q][0][0]+stany[q][0][2]>0 && stany[q][1][1]+stany[q][1][2]>0) { moge[n+1]=1; moge[q]=2; return true; } if (stany[q][0][0]+stany[q][0][2]>0 && stany[q][1][1]+stany[q][1][2]==0) //da sie zrobic [0 0] a nie da [1 1] { if (kolor_startowy[q]==1) { moge[n+1]=1; // da sie zrobic napewno if (stany[q][0][1]==0) //nigdzie nie treba uzywac [0][0] moge[q]=2; else moge[q]=1; } if (kolor_startowy[q]==0) { moge[n+1]=1; // da sie zrobic napewno if (stany[q][1][0]==0) //nigdzie nie treba uzywac [0][0] moge[q]=2; else moge[q]=0; } return true; } if (stany[q][1][1]+stany[q][1][2]>0 && stany[q][0][0]+stany[q][0][2]==0) { if (kolor_startowy[q]==0) { moge[n+1]=1; // da sie zrobic napewno if (stany[q][1][0]==0) //nigdzie nie treba uzywac [1][1] moge[q]=2; else moge[q]=0; } if (kolor_startowy[q]==1) { moge[n+1]=1; // da sie zrobic napewno if (stany[q][0][1]==0) //nigdzie nie treba uzywac [0][0] moge[q]=2; else moge[q]=1; } return true; } } // nie udalo sie majac ten kolor - musze zmienic go na czarny i zalozyc ze musze miec przeciwny if (kolor_startowy[q]==1) moge[q]=0; else moge[q]=1; if (q==1) { moge[n+1]=0; } //moge[n+1]=0; return false; } int main() { string s,c; int T,a,b; cin>>T; while(T--) { cin>>n; for (int i=0; i<=n; i++) { moge[i]=-1; graf[i].clear(); for (int j=0; j<2; j++) for (int k=0; k<3; k++) stany[i][j][k]=0; } cin>>kolor_st; cin>>kolor_do; if (n==1 && kolor_st[0]==kolor_do[0]) { cout<<"TAK\n"; continue; } if (n==1 && kolor_st[0]!=kolor_do[0]) { cout<<"NIE\n"; continue; } for (int i=0; i<n-1; i++) { cin>>a>>b; graf[a].push_back(b); graf[b].push_back(a); } for (int i=0; i<n; i++) { kolor_startowy[i+1]=kolor_st[i]-'0'; kolor_docelowy[i+1]=kolor_do[i]-'0'; } moge[n+1]=1; // zakladam najpierw ze sie da nowy_korzen=1; bool x=DFS(1); if (moge[n+1]==1) //udalo sie ukorzeniajac w 1 cout<<"TAK\n"; else cout<<"NIE\n"; } return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | #include <iostream> #include <cstdio> #include <algorithm> #include <vector> using namespace std; vector <int> graf[1000003]; string kolor_st; string kolor_do; int kolor_startowy[1000003]; int kolor_docelowy[1000003]; int moge[1000003]; int stany[1000003][2][3]; // [i][j][k] tyle razy synowie i wymagali skoczyc z j a mogli miec wartosc k int n; int nowy_korzen=-1; bool DFS(int q) { // cout<<"q="<<q<<" "; moge[q]=-2; for (int i=0; i<graf[q].size(); i++) { if (moge[graf[q][i]]==-1) DFS(graf[q][i]); else continue; int syn=graf[q][i]; //mamy juz przetworzone poddrzewo syn <=> w moge[] na pozycji syn jest dobra wartosc (0,1,2) stany[q][kolor_docelowy[syn]][moge[syn]]++; // cout<<"syn= "<<syn<<", stany["<<q<<"]["<<kolor_docelowy[syn]<<"]["<<moge[syn]<<"]="<<stany[q][kolor_docelowy[syn]][moge[syn]]<<"\n"; } // pamietamy, ze maja do dyspozycji tez moj kolor poczatkowy if (graf[q].size()==1 && q!=nowy_korzen) // jest lisciem to da sie zrobic synow liscia czyli nic { moge[n+1]=1; // informacja ze sie da poddrzewo moge[q]=kolor_startowy[q]; //informacja z jakim kolorem moge byc uzywajac tylko poddrzewa // cout<<"TU"; return true; } else { if (stany[q][0][0]+stany[q][0][2]>0 && stany[q][1][1]+stany[q][1][2]>0) { moge[n+1]=1; moge[q]=2; return true; } if (stany[q][0][0]+stany[q][0][2]>0 && stany[q][1][1]+stany[q][1][2]==0) //da sie zrobic [0 0] a nie da [1 1] { if (kolor_startowy[q]==1) { moge[n+1]=1; // da sie zrobic napewno if (stany[q][0][1]==0) //nigdzie nie treba uzywac [0][0] moge[q]=2; else moge[q]=1; } if (kolor_startowy[q]==0) { moge[n+1]=1; // da sie zrobic napewno if (stany[q][1][0]==0) //nigdzie nie treba uzywac [0][0] moge[q]=2; else moge[q]=0; } return true; } if (stany[q][1][1]+stany[q][1][2]>0 && stany[q][0][0]+stany[q][0][2]==0) { if (kolor_startowy[q]==0) { moge[n+1]=1; // da sie zrobic napewno if (stany[q][1][0]==0) //nigdzie nie treba uzywac [1][1] moge[q]=2; else moge[q]=0; } if (kolor_startowy[q]==1) { moge[n+1]=1; // da sie zrobic napewno if (stany[q][0][1]==0) //nigdzie nie treba uzywac [0][0] moge[q]=2; else moge[q]=1; } return true; } } // nie udalo sie majac ten kolor - musze zmienic go na czarny i zalozyc ze musze miec przeciwny if (kolor_startowy[q]==1) moge[q]=0; else moge[q]=1; if (q==1) { moge[n+1]=0; } //moge[n+1]=0; return false; } int main() { string s,c; int T,a,b; cin>>T; while(T--) { cin>>n; for (int i=0; i<=n; i++) { moge[i]=-1; graf[i].clear(); for (int j=0; j<2; j++) for (int k=0; k<3; k++) stany[i][j][k]=0; } cin>>kolor_st; cin>>kolor_do; if (n==1 && kolor_st[0]==kolor_do[0]) { cout<<"TAK\n"; continue; } if (n==1 && kolor_st[0]!=kolor_do[0]) { cout<<"NIE\n"; continue; } for (int i=0; i<n-1; i++) { cin>>a>>b; graf[a].push_back(b); graf[b].push_back(a); } for (int i=0; i<n; i++) { kolor_startowy[i+1]=kolor_st[i]-'0'; kolor_docelowy[i+1]=kolor_do[i]-'0'; } moge[n+1]=1; // zakladam najpierw ze sie da nowy_korzen=1; bool x=DFS(1); if (moge[n+1]==1) //udalo sie ukorzeniajac w 1 cout<<"TAK\n"; else cout<<"NIE\n"; } return 0; } |