Gym - 101503I 利用到图论的构造
Posted 天翎月
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gym - 101503I 利用到图论的构造相关的知识,希望对你有一定的参考价值。
比赛的时候没有注意到 给出的up矩阵 能使我们随便选一列 确定这一列的rank
这样我们得出每一行列的rank 进行构图 大->小 然后从大到小放 当前放的点 和他有因果关系并且比他大的点必须已经被放了 并且这个图没有环
做一个topsort就可以了
但是会MLE 因为边的数量可能 600^3 这个图虽然满足拓扑图 但是它比拓扑图更满足一个严格的等级序列
所以可以只建600^2的边 每个点指向只比它小的点
需要判断输入的合法性
int n ; int le[605][605] ; int up[605][605] ; int d[605][605] ; int deg[605*605] ; int ans[605][605] ; int head[605 * 605] ; struct edge{ int v,nex; }b[605 * 605 * 2] ; int tot ; void add(int u,int v){ tot ++ ; b[tot].v=v ; b[tot].nex=head[u]; head[u]=tot ; } bool topso() { int cnt = n*n ; queue<int>que ; while(!que.empty()) que.pop() ; rep(i,1,n*n) { if(deg[i] == 0) { que.push(i) ; } } while(!que.empty()) { int u = que.front() ; que.pop() ; int x = (u+n-1)/n; int y = (u%n) ; if(y==0)y=n; ans[x][y] = cnt -- ; rnode(i,u){ int v=b[i].v; deg[v]--; if(deg[v]==0){ que.push(v) ; } } } return cnt == 0 ; } int main () { tot = 0 ; flc(head,-1) ; n = read() ; rep(i,1,n) rep(j,1,n) up[i][j] = read() ; rep(i,1,n) rep(j,1,n) le[i][j] = read() ; rep(i,1,n) rep(j,1,n) { if(up[i][j] >= i || le[i][j] >= j) { printf("0\n") ; return 0 ; } } rep(i,1,n) rep(j,1,n) d[i][j] = (i-1)*n + j ; flc(deg,0) ; rep(i,1,n) { int a[650] ; a[1] = d[i][1] ; rep(j,2,n) { int m = le[i][j] ; m ++ ; dow(k,j,m+1) a[k] = a[k-1] ; a[m] = d[i][j] ; } rep(j,1,n-1) { add(a[j],a[j+1]) ; deg[a[j+1]] ++ ; } } rep(j,1,n) { int a[650] ; a[1] = d[1][j] ; rep(i,2,n) { int m = up[i][j] ; m ++ ; dow(k,i,m+1) a[k] = a[k-1] ; a[m] = d[i][j] ; } rep(i,1,n-1) { add(a[i],a[i+1]) ; deg[a[i+1]] ++ ; } } if(topso()) { rep(i,1,n) rep(j,1,n) { printf("%d" , ans[i][j]) ; fmt(j,n) ; } } else { printf("0\n") ; } }
以上是关于Gym - 101503I 利用到图论的构造的主要内容,如果未能解决你的问题,请参考以下文章