解析:
我是真没往图论想。。。
构图方法就是对于每一个行,排一个序,将数值小的向数值大的列连有向边,对于相同的数字建一个虚点,然后将这些数字给它连边就行了。然后拓扑排序,有环输出-1。
代码:
#include <bits/stdc++.h>
using namespace std;
const int Max=1000010;
const int inf=1e9;
int n,m,tot,size,head,tail,t,pos,k;
int first[Max],to[Max],ans[Max],p[Max],vis[Max];
struct shu{int to,next;};
shu edge[Max<<1];
struct jz{int id,num;};
jz a[Max];
inline int get_int()
{
int x=0,f=1;
char c;
for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
if(c=='-') {f=-1;c=getchar();}
for(;isdigit(c);c=getchar()) x=(x<<1)+(x<<3)+c-'0';
return x*f;
}
inline bool comp(const jz &a,const jz &b){return a.num<b.num;}
inline void build(int x,int y)
{
edge[++size].next=first[x];
first[x]=size;
edge[size].to=y;
to[y]++;
}
inline bool topsort()
{
queue<int>q;
for(int i=m+1;i<=t;i++)if(!to[i] && vis[i]) q.push(i);
int sum=0;head=tail=0;
while(sum<k)
{
head=0;
if(!q.size()) return 0;
while(q.size())
{
int i=q.front();q.pop();
to[i]=inf,p[++head]=i,sum++;
if(i<=m) ans[++tail]=i;
}
for(register int i=1;i<=head;i++)
for(register int u=first[p[i]];u;u=edge[u].next)
{
to[edge[u].to]--;
if(!to[edge[u].to]) q.push(edge[u].to);
}
}
for(int i=1;i<=m;i++) if(!vis[i]) ans[++tail]=i;
return 1;
}
inline void print(int x)
{
if(x>9) print(x/10);
putchar('0'+x%10);
}
int main()
{
n=get_int(),m=get_int(),t=m+1;
for(int i=1;i<=n;i++)
{
pos=1,t++;
for(int j=1;j<=m;j++) a[j].num=get_int(),a[j].id=j;
sort(a+1,a+m+1,comp);
while(a[pos].num==-1) pos++;
head=tail=pos;
while(pos<=m)
{
while(a[pos+1].num==a[pos].num && pos<=m) pos++,tail++;
for(int j=head;j<=tail;j++) build(t-1,a[j].id),build(a[j].id,t),vis[a[j].id]=1;
vis[t-1]=1,vis[t]=1;head=tail=++pos,t++;
}
}
for(int i=1;i<=t;i++) if(vis[i]) k++;
if(topsort()) for(int i=1;i<=m;i++) print(ans[i]),putchar(' ');
else cout<<"-1";
return 0;
}