ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

http://uoj.ac/problem/41

每次选一个未放入答案排列的数字x,选还没被覆盖的最右的出现位置覆盖,如果这导致原先一个已决策的数字决策失效(即这一行已经覆盖过)则重新决策这个数字,递归进行至不冲突为止,由于增广路的长度为O(n),总时间复杂度不超过读入复杂度。

#include<bits/stdc++.h>
char ib[20000007],*ip=ib;
int _(){
    int x=0;
    while(*ip<48)++ip;
    while(*ip>47)x=x*10+*ip++-48;
    return x;
}
int T,n,m,v[207][407],as[207],del[207],pp[207],ps[207][207];
struct pos{
    int x,y;
};
void find(int);
void set(int x,int y,int c){
    del[x]=y;
    int z=as[x];
    as[x]=c;
    if(z)find(z);
}
void find(int x){
    while(1){
        int v=ps[x][pp[x]];
        if((v&65535)<del[v>>16])return set(v>>16,v&65535,x);
        --pp[x];
    }
}
int main(){
    fread(ib,1,sizeof(ib),stdin);
    for(T=_();T;--T){
        n=_(),m=_();
        for(int i=1;i<=n;++i){
            pp[i]=as[i]=0;
            del[i]=m+1;
            for(int j=1;j<=m;++j)v[i][j]=_();
        }
        for(int j=1;j<=m;++j){
            for(int i=1;i<=n;++i)if(v[i][j]){
                int x=v[i][j];
                ps[x][++pp[x]]=i<<16|j;
            }
        }
        for(int i=1;i<=n;++i)find(i);
        for(int i=1;i<=n;++i)printf("%d ",as[i]);puts("");
    }
    return 0;
}

 

posted on 2017-09-18 18:48  nul  阅读(178)  评论(0编辑  收藏  举报