#include using namespace std; class UnionFind{ private: vector par,siz; public: UnionFind(int N){ par.resize(N,-1); siz.resize(N,1); } int root(int x){ //連結成分の代表頂点を返す. if(par.at(x) == -1) return x; else return par.at(x) = root(par.at(x)); } bool unite(int u, int v){ //u,vを連結する 連結してた->false,した->trueを返す. u = root(u),v = root(v); if(u == v) return false; if(siz.at(u) < siz.at(v)) swap(u,v); //Union by size. par.at(v) = u; siz.at(u) += siz.at(v); return true; } bool issame(int u, int v){ //同じ連結成分ならtrue. if(root(u) == root(v)) return true; else return false; } int size(int pos){return siz.at(root(pos));} //posの連結成分の大きさを返す. }; int main(){ ios_base::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while(T--){ int N,M,K; cin >> N >> M >> K; int root = 0; vector> Graph(N); UnionFind Z(N); vector> more; while(M--){ int u,v; cin >> u >> v,u--,v--; if(Z.issame(u,v)) more.push_back({u,v}); else Graph.at(u).push_back(v),Graph.at(v).push_back(u),Z.unite(u,v); } vector D(N); { auto dfs = [&](auto dfs,int pos,int back) -> void { for(auto to : Graph.at(pos)) if(to != back) D.at(to) = D.at(pos)+1,dfs(dfs,to,pos); }; dfs(dfs,0,-1); } root = -1; for(auto [u,v] : more) if(D.at(u)%2 == D.at(v)%2) root = u; vector A(N),B(N); for(auto &b : B) cin >> b; if(root == -1){ auto dfs = [&](auto dfs,int pos,int back) -> void { long long sum = 0; for(auto to : Graph.at(pos)){ if(to == back) continue; dfs(dfs,to,pos); int ope = (B.at(to)-A.at(to)+K)%K; A.at(to) = B.at(to),sum += ope; } A.at(pos) = sum%K; }; dfs(dfs,0,-1); if(A == B) cout << "Yes\n"; else cout << "No\n"; } else{ auto dfs = [&](auto dfs,int pos,int back) -> void { long long sum = 0; for(auto to : Graph.at(pos)){ if(to == back) continue; dfs(dfs,to,pos); int ope = (B.at(to)-A.at(to)+K)%K; A.at(to) = B.at(to),sum += ope; } A.at(pos) = sum%K; }; dfs(dfs,root,-1); int diff = (B.at(root)-A.at(root)+K)%K; if(diff%2 && K%2 == 0) cout << "No\n"; else cout << "Yes\n"; } } }