#include <iostream> #include <set> #include <vector> #include <algorithm> #include <cstring> #include <cmath> #include <list> using namespace std; #undef _HOME_ #ifdef _HOME_ #define DEBUG(x) x #else #define DEBUG(x) #endif #define REP(x,n) for(int x=0;x<(n);++x) #define FOREACH(x,n) for(__typeof(n.begin()) x = (n).begin(); x != (n).end(); ++x) #define RESULT(x) {cout<<(x);return 0;} const int MAX_N = 100001; typedef pair<int,int> PII; int n; string current; string target; struct Vertex { set<int> edges; void inline clear() { edges.clear(); } int inline degree() { return edges.size(); } }; Vertex graph[MAX_N]; bool inline isLinear() { int deg1cnt=0; REP(x,n) if (graph[x].degree() > 2) { DEBUG(cerr<<"deg of "<<x<<" is "<<graph[x].degree()<<endl;) return false; } else if (graph[x].degree() == 1) ++deg1cnt; DEBUG(cerr<<"deg1cnt = "<<deg1cnt<<endl;) return deg1cnt == 2; } int inline findOtherNeighbour(int v, int n) { for(const int& neighbour : graph[v].edges) if (n != neighbour) return neighbour; return -1; } bool solveLinearFrom(int start) { int prev=-1; char currentStartsFrom = current[start]; char targetStartsFrom = target[start]; int currentGroups = 0; int targetGroups = 0; int index=start; char currentGroup = -1; char targetGroup = -1; while(index != -1) { DEBUG(cerr<<"processing "<<index<<endl;) if (current[index] != currentGroup) { currentGroup = current[index]; ++currentGroups; } if (target[index] != targetGroup) { targetGroup = target[index]; ++targetGroups; } int index2 = findOtherNeighbour(index, prev); DEBUG(cerr<<"found neighbour("<<index<<","<<prev<<") -> "<<index2<<endl;) prev = index; index = index2; } DEBUG(cerr<<"current groups: "<<currentStartsFrom<<" "<<currentGroups<<endl;) DEBUG(cerr<<"target groups: "<<targetStartsFrom<<" "<<targetGroups<<endl;) if (currentStartsFrom == targetStartsFrom) return targetGroups <= currentGroups; else return targetGroups < currentGroups; } bool solveLinear() { int forcesCnt=0; REP(x,n) { if (graph[x].degree()==1) { DEBUG(cerr<<"leaf: "<<x<<endl;) return solveLinearFrom(x); } } cerr << "something went terribly wrong " << __LINE__ << endl; return true; // should never happen } bool inline has(const string& s, char c) { return s.find(c) != string::npos; } const int VALIDATE_PASS = 1; const int VALIDATE_FAIL = -1; int validate() { // maybe there's nothing to change if (current == target) return VALIDATE_PASS; // cannot produce color if it's not present on current state if (has(target, '1') && !has(current, '1')) return VALIDATE_FAIL; if (has(target, '0') && !has(current, '0')) return VALIDATE_FAIL; // cannot produce if there is no target group with length of 2 bool anyGroup2 = false; REP(x,n) for(const int& neighbour : graph[x].edges) if (target[x] == target[neighbour]) { anyGroup2 = true; break; } if (!anyGroup2) return VALIDATE_FAIL; return 0; } bool test() { cin>>n>>current>>target; REP(x,n) { graph[x].clear(); } int a,b; REP(x,n-1) { cin>>a>>b; graph[a-1].edges.insert(b-1); graph[b-1].edges.insert(a-1); DEBUG(cerr<<"added edge "<<a-1<<"-"<<b-1<<" - currently "<<graph[a-1].degree()<<"/"<<graph[b-1].degree()<<" edges"<<endl;) } int preResult = validate(); if (preResult != 0) return preResult>0; if (isLinear()) { DEBUG(cerr<<"linear"<<endl;) return solveLinear(); } DEBUG(cerr<<"non linear"<<endl;) if (n >= 5) return true; // if we're here, we have connection of 4 vertices connected like this // A // /|\ // / | \ // B C D // we can solve it always if target A is not the only one of its color bool has0leaf = false; bool has1leaf; char rootColor; REP(x,n) { if (graph[x].degree() > 1) rootColor = target[x]; else if (target[x] == '0') has0leaf = true; else has1leaf = true; } return rootColor == '0' ? has0leaf : has1leaf; } int t; int main() { ios_base::sync_with_stdio(0); cin>>t; REP(x,t) cout << (test() ? "TAK" : "NIE") << endl; 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 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | #include <iostream> #include <set> #include <vector> #include <algorithm> #include <cstring> #include <cmath> #include <list> using namespace std; #undef _HOME_ #ifdef _HOME_ #define DEBUG(x) x #else #define DEBUG(x) #endif #define REP(x,n) for(int x=0;x<(n);++x) #define FOREACH(x,n) for(__typeof(n.begin()) x = (n).begin(); x != (n).end(); ++x) #define RESULT(x) {cout<<(x);return 0;} const int MAX_N = 100001; typedef pair<int,int> PII; int n; string current; string target; struct Vertex { set<int> edges; void inline clear() { edges.clear(); } int inline degree() { return edges.size(); } }; Vertex graph[MAX_N]; bool inline isLinear() { int deg1cnt=0; REP(x,n) if (graph[x].degree() > 2) { DEBUG(cerr<<"deg of "<<x<<" is "<<graph[x].degree()<<endl;) return false; } else if (graph[x].degree() == 1) ++deg1cnt; DEBUG(cerr<<"deg1cnt = "<<deg1cnt<<endl;) return deg1cnt == 2; } int inline findOtherNeighbour(int v, int n) { for(const int& neighbour : graph[v].edges) if (n != neighbour) return neighbour; return -1; } bool solveLinearFrom(int start) { int prev=-1; char currentStartsFrom = current[start]; char targetStartsFrom = target[start]; int currentGroups = 0; int targetGroups = 0; int index=start; char currentGroup = -1; char targetGroup = -1; while(index != -1) { DEBUG(cerr<<"processing "<<index<<endl;) if (current[index] != currentGroup) { currentGroup = current[index]; ++currentGroups; } if (target[index] != targetGroup) { targetGroup = target[index]; ++targetGroups; } int index2 = findOtherNeighbour(index, prev); DEBUG(cerr<<"found neighbour("<<index<<","<<prev<<") -> "<<index2<<endl;) prev = index; index = index2; } DEBUG(cerr<<"current groups: "<<currentStartsFrom<<" "<<currentGroups<<endl;) DEBUG(cerr<<"target groups: "<<targetStartsFrom<<" "<<targetGroups<<endl;) if (currentStartsFrom == targetStartsFrom) return targetGroups <= currentGroups; else return targetGroups < currentGroups; } bool solveLinear() { int forcesCnt=0; REP(x,n) { if (graph[x].degree()==1) { DEBUG(cerr<<"leaf: "<<x<<endl;) return solveLinearFrom(x); } } cerr << "something went terribly wrong " << __LINE__ << endl; return true; // should never happen } bool inline has(const string& s, char c) { return s.find(c) != string::npos; } const int VALIDATE_PASS = 1; const int VALIDATE_FAIL = -1; int validate() { // maybe there's nothing to change if (current == target) return VALIDATE_PASS; // cannot produce color if it's not present on current state if (has(target, '1') && !has(current, '1')) return VALIDATE_FAIL; if (has(target, '0') && !has(current, '0')) return VALIDATE_FAIL; // cannot produce if there is no target group with length of 2 bool anyGroup2 = false; REP(x,n) for(const int& neighbour : graph[x].edges) if (target[x] == target[neighbour]) { anyGroup2 = true; break; } if (!anyGroup2) return VALIDATE_FAIL; return 0; } bool test() { cin>>n>>current>>target; REP(x,n) { graph[x].clear(); } int a,b; REP(x,n-1) { cin>>a>>b; graph[a-1].edges.insert(b-1); graph[b-1].edges.insert(a-1); DEBUG(cerr<<"added edge "<<a-1<<"-"<<b-1<<" - currently "<<graph[a-1].degree()<<"/"<<graph[b-1].degree()<<" edges"<<endl;) } int preResult = validate(); if (preResult != 0) return preResult>0; if (isLinear()) { DEBUG(cerr<<"linear"<<endl;) return solveLinear(); } DEBUG(cerr<<"non linear"<<endl;) if (n >= 5) return true; // if we're here, we have connection of 4 vertices connected like this // A // /|\ // / | \ // B C D // we can solve it always if target A is not the only one of its color bool has0leaf = false; bool has1leaf; char rootColor; REP(x,n) { if (graph[x].degree() > 1) rootColor = target[x]; else if (target[x] == '0') has0leaf = true; else has1leaf = true; } return rootColor == '0' ? has0leaf : has1leaf; } int t; int main() { ios_base::sync_with_stdio(0); cin>>t; REP(x,t) cout << (test() ? "TAK" : "NIE") << endl; return 0; } |