#include <cstdio> #include <queue> #include <stack> #include <cstring> #include <iostream> using namespace std; const int NN=210; const int MM=100000; const int INF=0x3fffffff; inline int Abs(int x) { if (x>=0) return x; else return -x; } int n,m,S,T,NV,en,head[NN]; struct Edge { int u,v,f,c,next; } e[MM]; inline void add(int u,int v,int c,int f1,int f2) //这题的很多版本的流量都是用的邻接矩阵,我写惯了邻接表,强迫症下不喜欢矩阵了~ { e[en].u=u; e[en].v=v; e[en].c=c; e[en].f=f1; e[en].next=head[u]; head[u]=en++; e[en].u=v; e[en].v=u; e[en].c=-c; e[en].f=f2; e[en].next=head[v]; head[v]=en++; } int dis[NN],cou[NN],p[NN]; bool vis[NN]; int circle_spfa() { int i,u,v; stack<int> q;//找圈的spfa用栈感觉比用队列好,栈是深度优先的 for (i=0; i<NV; i++) dis[i]=INF,cou[i]=vis[i]=0; dis[T]=0; cou[T]++; q.push(T); while (!q.empty()) { u=q.top(); q.pop(); vis[u]=false; for (i=head[u]; i!=-1; i=e[i].next) { v=e[i].v; if (e[i].f && dis[v]>dis[u]+e[i].c) { dis[v]=dis[u]+e[i].c; p[v]=i; if (!vis[v]) { q.push(v); vis[v]=true; } if (++cou[v]>=NV) return v; } } } return -1; } int ans[NN][NN]; void solve() { int i,j,x,u,v; x=circle_spfa();//这题不需要求最优,spfa找负圈找一次即可 if (x==-1) { puts("OPTIMAL"); return; } puts("SUBOPTIMAL"); //单词拼错,贡献WA n次 memset(vis,0,sizeof(vis)); while (!vis[x]) { vis[x]=true; x=e[p[x]].u; }//spfa退出的点未必是负圈中的点 v=x; do { u=e[p[v]].u; e[p[v]].f--; e[p[v]^1].f++; v=u; }while (v!=x);//消圈 memset(ans,0,sizeof(ans)); for (i=0; i<en; i+=2) { if (!e[i^1].f || e[i].u==S || e[i].v==T) continue; ans[e[i].u][e[i].v-n]=e[i^1].f; } for (i=1; i<=n; i++) { for (j=1; j<m; j++) printf("%d ",ans[i][j]); printf("%d\n",ans[i][m]); } } int x[NN],y[NN],z[NN],s1[NN],s2[NN]; int main() { int i,j,diss,w; while (~scanf("%d%d",&n,&m)) { en=S=0; T=n+m+1; NV=T+1; memset(head,-1,sizeof(head)); for (i=1; i<=n+m; i++) scanf("%d%d%d",&x[i],&y[i],&z[i]); for (i=1; i<=m; i++) s2[i]=0; for (i=1; i<=n; i++) { s1[i]=0; for (j=1; j<=m; j++) { scanf("%d",&w); diss=Abs(x[i]-x[j+n])+Abs(y[i]-y[j+n])+1; s1[i]+=w; s2[j]+=w; add(i,j+n,diss,INF-w,w); } } for (i=1; i<=n; i++) add(S,i,0,z[i]-s1[i],s1[i]); for (i=1; i<=m; i++) add(i+n,T,0,z[i+n]-s2[i],s2[i]); solve(); } return 0; }