#include<stdio.h>
#include<string>
#include<iostream>
#include<vector>
#include<string.h>
#define maxint 2000000000
#define maxn 1024
using namespace std;
typedef struct edge{
long node, price;
};
long m[ maxn][ maxn];
class graph{
public :
vector< vector < edge > > list;
vector< vector <int> > mat;
int size; // number of nodes (usually n)
char type; // what kind of storage are we using 0 for list of neighbours 1 for li
private:
int add_edge_matrix( const int &a, const int &b, const int& cost)
{
//this ads an edge to the matrix
// if the values are greater than the size of the matrix then it returns 1
/// if edge allready exists in matrix -> it returns 0
int ret = 0;
if( a > size || b > size)
return 1;
if( mat[a][b] != -1)
ret = 2;
mat[ a][b] = cost;
return ret;
}
int add_edge_list( const int &a, const int &b, const int& cost2)
{
//this ads an edge to the matrix
// if the values are greater than the size of the matrix then it returns 1
// else returns 0
if( a > size || b > size)
return 1;
edge *temp = new edge();
(*temp).node = b;
(*temp).price = cost2;
list[a].push_back( (*temp));
return 0;
}
public:
graph(const int& get_size,int way = 0) {
type = way;
size = get_size;
if( way == 0) {
//we are creating the list of neighbours O(m)
for( long i = 1; i <= size; ++i) {
vector<edge> *a = new vector<edge>;
list.push_back( *a );
}
}
if( way == 1) {
// we create the matrix of neighbours O(n^2)
for( long i = 1; i <= size; ++i) {
vector<int> *a = new vector<int>(-1,size + 1);
mat.push_back( *a );
}
}
}
int add_edge( const int &a, const int &b, const int &c)
{
int rez;
if( type %2 == 0) // if type == 2 we add to both matrix and list if 0 only to list if 1 only to matrix
{
rez = add_edge_list( a - 1 , b - 1, c);
if( type == 0)
return rez;
}
return add_edge_matrix( a - 1 , b - 1, c);
}
void print_list()
{
printf("%d\n", size);
for( long i = 0; i < size; ++i)
{
printf("%ld : ", i + 1 );
long temp_n = list[i].size();
for( long j = 0; j < temp_n; ++j)
{
printf(" ( %ld, %ld )" , list[i][j].node + 1, list[i][j].price);
}
printf("\n");
}
}
};
class arb_int{
private:
int size;
int *vec;
int *index;
int *who;
short int type;
/* type = 0 -> min_tree
type = 1 -> sum_tree
*/
int real_size( const int& n){
// determines the size of the tree it has to be around twice as big as the information used
int w = 1;
while( w < n)
w *= 2;
w*= 2;
return w;
}
public:
arb_int ( const int& a, int typ = 0) {
size = real_size(a);
vec = new int[ size ];
int *info = new int[ a + 1];
index = new int[ a + 1 ];
type = typ;
for( int i = 0; i <= a; ++i)
info[i] = maxint;
if( type == 0)
{
who = new int[ size ];
}
create( 1, 1, a, info);
}
arb_int ( const int& a, int* info , int typ = 0) {
size = real_size(a);
type = typ;
vec = new int[ size ];
index = new int[ a + 1 ];
if( type == 0)
{
who = new int[ size ];
}
create( 1, 1, a, info);
}
void update_info( const int& nod)
{
if( type == 1){
vec[ nod ] = vec[ nod * 2] + vec[ nod * 2 + 1];
return ;
}
if( type == 0){
vec[ nod ] = vec[ nod * 2];
who[ nod ] = who[ nod * 2];
if( vec[ nod * 2 + 1] < vec[ nod] )
vec[ nod] = vec[ nod * 2 + 1], who[ nod ] = who [ nod * 2 + 1];
return;
}
}
void create( const int& nod, const int &left, const int &right, int* info)
{
if( left == right)
{
index[ left ] = nod;
vec[ nod ] = info[ left ];
if( type == 0)
who[ nod ] = left;
return;
}
create( nod * 2, left, ( left + right) /2, info);
create( nod * 2 + 1, ( left + right) / 2 + 1, right, info);
update_info( nod );
}
void modify( const int& nod, const int& new_info )
{
int temp_nod = index[ nod ];
vec[ temp_nod ] = new_info;
temp_nod /= 2;
while( temp_nod )
{
update_info( temp_nod);
temp_nod /= 2;
}
}
int get_top()
{
return vec[ 1 ];
}
int who_top()
{
return who[ 1 ];
}
void eliminate_top()
{
modify( who[ 1 ], maxint );
}
int get_element( const int &nod)
{
return vec[ index[ nod] ];
}
};
int rez[64 * 1024];
int rez2[64000];
int main()
{
freopen("distante.in","r",stdin);
freopen("distante.out","w",stdout);
int T;
scanf("%d",&T);
for( long ii = 1; ii <= T; ++ii)
{
long n,m,s;
scanf("%ld %ld %ld",&n,&m,&s);
for( long i = 1; i<= n; ++i)
scanf("%d", &rez2[i]);
graph g(n,0);
arb_int arb( n );
memset( rez, 0, sizeof(rez));
for( long i = 1; i <= m; ++i)
{
int node1, node2, cost;
scanf("%d %d %d",&node1, &node2, &cost);
g.add_edge( node1, node2, cost);
g.add_edge( node2, node1, cost);
if( node1 == s)
arb.modify( node2, cost);
if( node2 == s)
arb.modify( node1, cost);
}
arb.modify( s, maxint + 1);
rez[s] = -1;
//g.print_list();
for( long i = 1; i < n; ++i)
{
long curent = arb.who_top();
long value = arb.get_top();
if( value >= maxint)
break;
rez[ curent ] = value;
curent--;
//g.print_list();
for( unsigned int i = 0; i < g.list[ curent ].size(); ++i)
{
int neib = g.list[ curent ][i].node + 1;
if( rez[ neib ] != 0) continue;
if( arb.get_element( neib) > value + g.list[ curent][i].price )
arb.modify( neib, value + g.list[ curent][i].price );
}
arb.eliminate_top();
}
rez[s] = 0;
string sir("DA");
for( long i = 1; i <= n; ++i)
{
if( rez[i] != rez2[i])
sir = "NU";
}
cout<<sir<<endl;
}
return 0;
}