Problem:
Score : 900 points

Problem Statement

AtCoDeer the deer wants a directed graph that satisfies the following conditions:

The number of vertices, N, is at most 300.

There must not be self-loops or multiple edges.

The vertices are numbered from 1 through N.

Each edge has either an integer weight between 0 and 100 (inclusive), or a label X or Y.

For every pair of two integers (x,y) such that 1 ≤ x ≤ A, 1 ≤ y ≤ B,
the shortest distance from Vertex S to Vertex T in the graph where the edges labeled X have the weight x and the edges labeled Y have the weight y, is d_{x,y}.

Construct such a graph (and a pair of S and T) for him, or report that it does not exist.
Refer to Output section for output format.

Constraints

1 ≤ A,B ≤ 10

1 ≤ d_{x,y} ≤ 100 (1 ≤ x ≤ A, 1 ≤ y ≤ B)

All input values are integers.

Input

Input is given from Standard Input in the following format:

A B
d_{1,1} d_{1,2} .. d_{1,B}
d_{2,1} d_{2,2} .. d_{2,B}
:
d_{A,1} d_{A,2} .. d_{A,B}

Output

If no graph satisfies the condition, print Impossible.

If there exists a graph that satisfies the condition, print Possible in the first line.
Then, in the subsequent lines, print the constructed graph in the following format:

N M
u_1 v_1 c_1
u_2 v_2 c_2
:
u_M v_M c_M
S T

Here, M is the number of the edges, and u_i, v_i, c_i represent edges as follows: there is an edge from Vertex u_i to Vertex v_i whose weight or label is c_i.

Also refer to Sample Outputs.

Sample Input 1

2 3
1 2 2
1 2 3

Sample Output 1

Possible
3 4
1 2 X
2 3 1
3 2 Y
1 3 Y
1 3

Sample Input 2

1 3
100 50 1

Sample Output 2

Impossible

Solution in Rust (1.15.1) (judge verdict: Runtime Error)

// use std::ops::{Index, IndexMut};
// use std::cmp::{Ordering, min, max};
// use std::collections::{BinaryHeap, BTreeMap};
// use std::collections::btree_map::Entry::{Occupied, Vacant};
// use std::clone::Clone;

fn getline() -> String{
    let mut res = String::new();
    std::io::stdin().read_line(&mut res).ok();
    res
}

macro_rules! readl {
    ($t: ty) => {
        {
            let s = getline();
            s.trim().parse::<$t>().unwrap()
        }
    };
    ($( $t: ty),+ ) => {
        {
            let s = getline();
            let mut iter = s.trim().split(' ');
            ($(iter.next().unwrap().parse::<$t>().unwrap(),)*) 
        }
    };
}

macro_rules! readlvec {
    ($t: ty) => {
        {
            let s = getline();
            let iter = s.trim().split(' ');
            iter.map(|x| x.parse().unwrap()).collect::<Vec<$t>>()
        }
    }
}

macro_rules! debug {
    ($x: expr) => {
        println!("{}: {:?}", stringify!($x), $x)
    }
}

fn printiter<'a, T>(v: &'a T)
where
    &'a T: std::iter::IntoIterator, 
    <&'a T as std::iter::IntoIterator>::Item: std::fmt::Display {
    for (i,e) in v.into_iter().enumerate() {
        if i != 0 {
            print!(" ");
        }
        print!("{}", e);
    }
    println!("");
}

struct ContestPrinter {
    s: String,
}

impl ContestPrinter {
    fn new() -> ContestPrinter {
        ContestPrinter {
            s: String::new(),
        }
    }

    fn print<T>(&mut self, x: T)
        where T: std::fmt::Display {
        self.s.push_str(format!("{}", x).as_str());
    }

    fn println<T>(&mut self, x: T)
        where T: std::fmt::Display {
        self.s.push_str(format!("{}\n", x).as_str());
    }
}

impl std::ops::Drop for ContestPrinter {
    fn drop(&mut self) {
        print!("{}", self.s);
    }
}

struct Graphmat {
    mat: Vec<Vec<Option<i32>>>,
    s: usize, 
    t: usize,
    ud: usize,
}

impl Graphmat {
    fn new() -> Self {
        let n = 300;
        let mut mat = vec![vec![None; n]; n];
        for i in 0..100 {
            mat[i][i+1] = Some(-1); // x
        }
        for i in 0..100 {
            mat[101+i+1][101+i] = Some(-2); // y
        }
        Graphmat {
            mat: mat,
            s: 0,
            t: 101,
            ud: 202,
        }
    }
    
    fn add(&mut self, a: i32, b: i32, c: i32) {
        let a = a as usize;
        let b = b as usize;
        if self.mat[a][101+b] == None {
            self.mat[a][101+b] = Some(c);
        } else {
            self.mat[a][self.ud] = Some(0);
            self.mat[self.ud][101+b] = Some(c);
            // debug!(self.ud);
            self.ud += 1;
        }
    }
}


fn main() {
    let mut printer = ContestPrinter::new();
    let (a, b) = readl!(usize, usize);
    let mut d = Vec::with_capacity(b);
    // assert!(b != 1);
    for _ in 0..a {
        d.push(readlvec!(i32));
    }
    let im = "Impossible";
    let n = 300;
    let ans = if b == 1 {
        let mut ans = vec![vec![(0, 0, 0); 1]; a];
        for i in 0..a-1 {
            let ym = 0;
            let xm = d[i+1][0]-d[i][0];
            let c = d[i][0] - xm * (i as i32 + 1);
            if xm < 0 || ym < 0 || c < 0 {
                printer.println(im);
                return;
            }
            ans[i][0] = (xm, ym, c);
        }
        let i = a-1;
        let ym = 0;
        let xm = 0;
        let c = d[i][0];
        if xm < 0 || ym < 0 || c < 0 {
            // debug!((i, j, xm, ym, c));
            printer.println(im);
            return;
        }
        ans[i][0] = (xm, ym, c);
        
        
        ans
    } else {
        let mut ans = vec![vec![(0, 0, 0); b-1]; a];
        for i in 0..a-1 {
            for j in 0..b-1 {
                let ym = d[i][j+1]-d[i][j];
                let xm = std::cmp::max(d[i+1][j]-d[i][j], d[i+1][j+1]-d[i][j+1]);
                let c = d[i][j] - ym * (j as i32 + 1) - xm*(i as i32 + 1);
                if xm < 0 || ym < 0 || c < 0 {
                    // debug!((i, j, xm, ym, c));
                    printer.println(im);
                    return;
                }
                ans[i][j] = (xm, ym, c);
            }
        }
        for j in 0..b-1 {
            let i = a-1;
            let ym = d[i][j+1]-d[i][j];
            let xm = 0;
            let c = d[i][j] - ym * (j as i32 + 1) - xm*(i as i32 + 1);
            if xm < 0 || ym < 0 || c < 0 {
                // debug!((i, j, xm, ym, c));
                printer.println(im);
                return;
            }
            ans[i][j] = (xm, ym, c);
        }
        ans
    };
    
    let mut ls = std::collections::HashSet::new();
    for vec in ans {
        for e in vec {
            ls.insert(e);
        }
    }
    let ls = ls;


    // debug!(ls);
    {
        let calc = |x, y| {
            ls.iter().map(|&(a, b, c)| a*x+b*y+c).min().unwrap()
        };
        for x in 1..a+1 {
            for y in 1..b+1 {
                // print!("{} ", calc(x as i32, y as i32));
                if d[x-1][y-1] != calc(x as i32, y as i32) {
                    printer.println(im);
                    return;
                }
            }
            // println!();
        }
    }

    // debug!(ls);
    let mut g = Graphmat::new();
    for (a, b, c) in ls {
        g.add(a, b, c);
    }
    let mut cnt = 0;
    for i in 0..g.mat.len() {
        for j in 0..g.mat[i].len() {
            if let Some(_) = g.mat[i][j] {
                cnt += 1;
            }
        }
    }
    assert!(false);
    printer.println("Possible");
    printer.println(format!("{} {}", 300, cnt));
    for i in 0..g.mat.len() {
        for j in 0..g.mat[i].len() {
            if let Some(v) = g.mat[i][j] {
                if v == -1 {
                    printer.println(format!("{} {} X", i+1, j+1));
                } else if v == -2 {
                    printer.println(format!("{} {} Y", i+1, j+1));
                } else {
                    printer.println(format!("{} {} {}", i+1, j+1, v));
                }
            }
        }
    }
    printer.println(format!("{} {}", g.s+1, g.t+1));
}