/**/ /*
    一个图
    每条边上有两个值(gcd,lcm) 其值是该边两个顶点u,v上值的gcd和lcm
    现给出一些边,问有没存在顶点的值满足边的限制
    n <= 100 , m <= n(n-1)/2
    1 <= gcd , lcm <= 10^6

    由于gcd , lcm比较小
    选取任意一个顶点,枚举它的值val,val要满足val % gcd == 0 , lcm % val == 0
    for( val = gcd ; val <= lcm ; val += gcd)
        if( lcm % val == 0)
            检查
    由lcm = a * b / gcd ,知道了a就推出b了
    所以由选取的那个点出发,去推出其他点的值,若之前已经推出了,判断其是否矛盾
*/

#include
< iostream >
#include
< cstring >
#include
< map >
#include
< algorithm >
#include
< stack >
#include
< queue >
#include
< cmath >
#include
< string >
#include
< cstdlib >
#include
< vector >
#include
< cstdio >
#include
< set >
#include
< list >

using   namespace  std;

struct  Edge {
    
int v , l , g;
    Edge(
int v , int g , int l): v(v), g(g), l(l){
    }

}
;

vector
< Edge >  E[ 101 ];
int  ans[ 101 ];
stack
< int >  s;

int  gcd( int  a ,  int  b) {
    
return b == 0 ? a : gcd(b , a % b);
}


int  lcm( int  a , int  b) {
    
return a / gcd(a,b) * b;
}



bool  chk( int  u) {
    s.push(u);
    
for(vector<Edge>::iterator it = E[u].begin() ; it != E[u].end() ; it++){
        
int v = it->v , g = it->g , l = it->l;
        
if(l % ans[u] != 0 || ans[u] % g != 0){
            
return false;
        }

        
if(ans[v] != -1){
            
if(gcd(ans[u], ans[v]) != g || lcm(ans[u], ans[v]) != l){
                
return false;
            }

        }
else{
            ans[v] 
= l / ans[u] * g ;
            
if(!chk(v)){
                
return false;
            }

        }

    }

    
return true;
}


bool  gao( int  u) {
    
if(E[u].empty()){
        ans[u] 
= 1;
        
return true;
    }

    
while(!s.empty()){//don't forget !!!
        s.pop();
    }

    Edge e 
= E[u][0];
    
int g = e.g , l = e.l;
    
for(int val = g ; val <= l ; val += g){
        
if(l % val !=0){
            
continue;
        }
        
        ans[u] 
= val;
        
if(chk(u)){
            
return true;
        }
else{
            
while(!s.empty()){
                ans[s.top()] 
= -1;
                s.pop();
            }

        }

    }

    
return false;
}


int  main()
{
    
for(int n, m; ~scanf("%d%d",&n, &m); ){
        
for(int i = 1 ; i <= n ; i ++){
            E[i].clear();
        }

        
bool err = false;
        
for(int i = 0 ; i < m ; i ++){
            
int u, v, g, l;
            scanf(
"%d%d%d%d",&u,&v,&g,&l);
            E[u].push_back(Edge(v, g, l));
            E[v].push_back(Edge(u, g, l));
            
if(l % g != 0){
                err 
= true;
            }

        }


        
if(!err){
            fill(ans
+1,ans+1+n,-1);
            
for(int u = 1 ; u <= n; u++){
                
if(ans[u] == -1){
                    
if(!gao(u)){
                        err 
= true;
                        
break;
                    }

                }

            }

        }


        
if(err){
            puts(
"NO");
        }
else{
            puts(
"YES");
            
for(int i = 1 ; i <= n ; i++){
                
if(i>1){
                    putchar(
' ');
                }

                printf(
"%d",ans[i]);
            }

            puts(
"");
        }

    }
    
    
return 0;
}