Cod sursa(job #346712)

Utilizator marius135Dumitran Adrian Marius marius135 Data 9 septembrie 2009 11:51:29
Problema Distante Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.8 kb
#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 type = 0)	{
		
		size = real_size(a);
		vec = new int[ size ];
		int *info = new int[ a + 1];
		index = new int[ a + 1 ];
		
		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 type = 0)	{
		size = real_size(a);
		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);
			if( node1 == s)
				arb.modify( node2, cost);
					
		}
		arb.modify( s, maxint + 1);
		
		//g.print_list();
		memset( rez,0,sizeof(rez));
		
		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();
			
		}
		
		string sir("DA");
		for( long i = i; i <= n; ++i)
		{
			if( rez[i] != rez2[i])
				sir = "NU";
		}
		cout<<sir<<endl;
		
	
	
	}
	
	
	return 0;
}