习题:Table Compression

题目

传送门

思路

很明显,对于同一列或同一行中相同的数的权值一定是一样的,用并查集进行缩点即可

之后把大于和小于转换成图上的边,跑拓扑即可

代码

#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
namespace IO
{
    void read(int &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void write(int x)
    {
        if(x<10)
            putchar(x+'0');
        else
        {
            write(x/10);
            putchar(x%10+'0');
        }
    }
}
namespace ufs
{
    int fa[1000005];
    void makeset(int n)
    {
        for(int i=0;i<n;i++)
            fa[i]=i;
    }
    int findset(int x)
    {
        if(fa[x]==x)
            return x;
        return fa[x]=findset(fa[x]);
    }
    void merge(int u,int v)
    {
        int a=findset(u);
        int b=findset(v);
        fa[a]=b;
    }
}
using namespace ufs;
using namespace IO;
int n,m;
bool used[1000005];
int id[1000005],d[1000005];
queue<int> q;
map<int,int> f;
vector<int> v[1000005],g[1000005];
int change(int x,int y)
{
    return x*m+y;
}
void topsort()
{
    for(int i=0;i<n*m;i++)
    {
        if(d[findset(i)]==0&&used[findset(i)]==0)
        {
            used[findset(i)]=1;
            id[findset(i)]=1;
            q.push(findset(i));
        }
    }
    while(!q.empty())
    {
        int u=q.front();
        u=findset(u);
        q.pop();
        for(int i=0;i<g[u].size();i++)
        {
            int v=g[u][i];
            v=findset(v);
            d[v]--;
            if(d[v]>=0)
                id[v]=max(id[v],id[u]+1);
            if(d[v]==0)
                q.push(v);
        }
    }
}
int main()
{
    read(n);read(m);
    makeset(n*m);
    for(int i=0;i<n;i++)
    {
        v[i].resize(m);
        for(int j=0;j<m;j++)
            read(v[i][j]);
    }
    for(int i=0;i<n;i++)
    {
        f.clear();
        for(int j=0;j<m;j++)
        {
            if(f.count(v[i][j])==0)
                f[v[i][j]]=change(i,j);
            else 
                merge(change(i,j),findset(f[v[i][j]]));  
        }
    }
    for(int j=0;j<m;j++)
    {
        f.clear();
        for(int i=0;i<n;i++)
        {
            if(f.count(v[i][j])==0)
                f[v[i][j]]=change(i,j);
            else 
                merge(change(i,j),findset(f[v[i][j]]));  
        }
    }
    for(int i=0;i<n;i++)
    {
        f.clear();
        vector<int> s;
        for(int j=0;j<m;j++)
        {
            if(f.count(v[i][j])==0)
            {
                f[v[i][j]]=change(i,j);
        		s.push_back(v[i][j]);
        	}
        }
        sort(s.begin(),s.end());
        for(int i=s.size()-1;i>=1;i--)
        {
            g[findset(f[s[i-1]])].push_back(findset(f[s[i]]));
            d[findset(f[s[i]])]++;
        }
    }
    for(int j=0;j<m;j++)
    {
        f.clear();
        vector<int> s;
        for(int i=0;i<n;i++)
        {
            if(f.count(v[i][j])==0)
            {
                f[v[i][j]]=change(i,j);
            	s.push_back(v[i][j]);
            }
        }
        sort(s.begin(),s.end());
        for(int i=s.size()-1;i>=1;i--)
        {
            g[findset(f[s[i-1]])].push_back(findset(f[s[i]]));
            d[findset(f[s[i]])]++;
        }
    }

    topsort();
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            write(id[findset(change(i,j))]);
            putchar(' ');
        }
        putchar('\n');
    }
    return 0;
}
/*
2 3
2 1 3
5 4 3
*/
posted @ 2020-08-24 10:07  loney_s  阅读(66)  评论(0)    收藏  举报