【拓撲排序】Gym - 101503 - I.Just Matrix
阿新 • • 發佈:2018-12-25
題目連結<http://codeforces.com/gym/101503/problem/I>
題意:
有一個n*n的矩陣,裡面的數字為1~n*n,給出每個位置在它上邊和左邊有多少個大於它的數。構造出這麼一個矩陣。
題解:
可以得知每一行每一列的大小順序,每一行每一列從小到大依次連邊。
如果從小到大依次填入數字,這樣就能夠確定因果關係。
然後做一次拓撲排序判斷有無結果並輸出即可。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=6e2+7; const int M=1e6+7; int a[N][N],b[N][N],n; int od[N]; struct Edge{ int u,v,nxt; Edge(int u=0,int v=0,int nxt=0):u(u),v(v),nxt(nxt){} }e[M]; int p[M],edn; void add(int u,int v){ e[++edn]=Edge(u,v,p[u]);p[u]=edn; } int ans[N][N],d[N*N]; bool Tsort(){ queue<int>q; for(int i=0;i<n*n;i++){ if(d[i]==0) q.push(i); } int cnt=0; while(!q.empty()){ int u=q.front();q.pop(); ans[u/n][u%n]=++cnt; for(int i=p[u];~i;i=e[i].nxt){ int v=e[i].v; d[v]--; if(d[v]==0) q.push(v); } } if(cnt<n*n) return false; return true; } int main() { memset(p,-1,sizeof(p));edn=-1; scanf("%d",&n); for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&a[i][j]); bool flag=true; for(int j=0;j<n;j++){ memset(od,-1,sizeof(od)); for(int i=n-1;i>=0;i--){ int tmp=a[i][j]; int id=i*n+j; int k=n-1; while(tmp&&k>=0){ if(od[k]==-1) tmp--; k--; } while(od[k]!=-1&&k>=0) k--; if(k<0){flag=false;break;} else od[k]=id; } if(!flag) break; for(int k=0;k<n-1;k++){ add(od[k],od[k+1]); d[od[k+1]]++; } } for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&b[i][j]); for(int i=0;i<n;i++){ memset(od,-1,sizeof(od)); for(int j=n-1;j>=0;j--){ int tmp=b[i][j]; int id=i*n+j; int k=n-1; while(tmp&&k>=0){ if(od[k]==-1) tmp--; k--; } while(od[k]!=-1&&k>=0) k--; if(k<0){flag=false;break;} else od[k]=id; } if(!flag) break; for(int k=0;k<n-1;k++){ add(od[k],od[k+1]); d[od[k+1]]++; } } if(!flag||!Tsort()){printf("0\n");return 0;} for(int i=0;i<n;i++){ for(int j=0;j<n;j++) printf("%d ",ans[i][j]); printf("\n"); } }