#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 1005

struct Edge{
	Edge(int arg_to,int arg_capacity,int arg_rev_index){
		to = arg_to;
		capacity = arg_capacity;
		rev_index = arg_rev_index;
	}
	int to,capacity,rev_index;
};

int N;
int V;
int rank_index[NUM],component_index[NUM],rev_component[NUM];
vector<Edge> G[NUM];
int dist[NUM];
int cheked_index[NUM];

void add_edge(int from,int to,int capacity){
	G[from].push_back(Edge(to,capacity,G[to].size()));
	G[to].push_back(Edge(from,0,G[from].size()-1));
}

void delete_edge(int from,int index){

	G[from][index].capacity = 0;
	int rev_from = G[from][index].to;

	int left = 0,right = G[rev_from].size()-1,mid = (left+right)/2;

	while(left <= right){

		if(G[rev_from][mid].to == from){

			G[rev_from][mid].capacity = 0;
			return;

		}else if(G[rev_from][mid].to > from){

			right = mid-1;

		}else{
			left = mid+1;
		}
		mid = (left+right)/2;
	}
}

void bfs(int source){
	for(int i = 0; i < V; i++)dist[i] = -1;
	queue<int> Q;
	dist[source] = 0;
	Q.push(source);

	while(!Q.empty()){
		int node_id = Q.front();
		Q.pop();
		for(int i = 0; i < G[node_id].size(); i++){
			Edge &e = G[node_id][i];
			if(e.capacity > 0 && dist[e.to] < 0){
				dist[e.to] = dist[node_id]+1;
				Q.push(e.to);
			}
		}
	}
}

int dfs(int node_id,int sink,int flow){
	if(node_id == sink)return flow;

	for(int &i = cheked_index[node_id]; i < G[node_id].size(); i++){
		Edge &e = G[node_id][i];
		if(e.capacity > 0 && dist[node_id] < dist[e.to]){
			int tmp_flow = dfs(e.to,sink,min(flow,e.capacity));
			if(tmp_flow > 0){
				e.capacity -= tmp_flow;
				G[e.to][e.rev_index].capacity += tmp_flow;
				return tmp_flow;
			}
		}
	}
	return 0;
}


int max_flow(int source,int sink){
	int flow = 0,add;
	while(true){
		bfs(source);
		if(dist[sink] < 0)break;
		for(int i = 0; i < V; i++)cheked_index[i] = 0;
		while((add = dfs(source,sink,BIG_NUM)) > 0){
			flow += add;
		}
	}
	return flow;
}

bool find_a_path(int source,int sink){

	bfs(source);

	if(dist[sink] < 0){
		return false;
	}

	for(int i = 0; i < V; i++)cheked_index[i] = 0;

	return dfs(source,sink,1) == 1;
}

int main(){

	scanf("%d",&N);

	int source = 0,sink = 1;
	int index = 2;

	for(int i = 0; i <= N-2; i++){

		rank_index[i] = index++;
		add_edge(source,rank_index[i],1);
	}

	for(int i = 0; i <= N-2; i++){

		component_index[i] = index++;
		rev_component[component_index[i]] = i;
		add_edge(component_index[i],sink,1);
	}

	V = index;

	int tmp;

	for(int i = 0; i <= N-2; i++){
		for(int k = 0; k <= N-2; k++){

			scanf("%d",&tmp);
			if(tmp == 1){
				add_edge(rank_index[k],component_index[i],1);
			}
		}
	}

	if(max_flow(source,sink) < N-1){

		printf("no\n");
		return 0;
	}

	printf("yes\n");

	for(int rank = rank_index[0]; rank <= rank_index[N-2]; rank++){

		for(int i = G[rank].size()-1; i >= 0; i--){

			if(G[rank][i].capacity == 1){

				delete_edge(rank,i);

			}else{

				if(find_a_path(rank,G[rank][i].to)){

					delete_edge(rank,i);

				}else{

					printf("%d\n",rev_component[G[rank][i].to]+1);
					break;
				}
			}
		}
	}

	return 0;
}

