关闭

Codeforces 650C Table Compression (并查集+拓扑排序)

92人阅读 评论(0) 收藏 举报
分类:

解析:不看tags都意识不到用图论。

一个位置对应一个节点,对于每行每列,值相同的用并查集union一起,值不相同的,值小的节点指向值大的节点。

压缩后节点的值是到该节点的最长的链的长度,可以通过拓扑排序求得。


[code]:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>

using namespace std;
const int maxn = 1e6+5;

struct Nod{
    int b,next;
    void init(int b,int next){
        this->b=b;this->next=next;
    }
}buf[maxn<<2];
int n,m,a[maxn],b[maxn],d[maxn],deg[maxn];
int V,len,E[maxn],par[maxn];
int ord[maxn];
queue<int> que;

bool cmp(const int &i,const int &j){
    return a[i] < a[j];
}

void init(){
    V = n*m;
    len = 0;
    memset(E,-1,sizeof(E));
    for(int i = 0;i < V;i++) par[i] = i;
}
int find(int x){
    return par[x]==x?x:par[x]=find(par[x]);
}
void unite(int x,int y){
    x = find(x),y = find(y);
    if(x == y) return;
    par[y] = x;
}
void add_edge(int a,int b){
    buf[len].init(b,E[a]);E[a]=len++;
    deg[b]++;
}
void pre_preocess(){
    int i,j;
    for(i = 0;i < n;i++){
        for(j = 0;j < m;j++){
            ord[j] = i*m+j;
        }
        sort(ord,ord+m,cmp);
        for(j = 1;j < m;j++){
            if(a[ord[j-1]]==a[ord[j]]) unite(ord[j],ord[j-1]);
        }
    }
    for(j = 0;j < m;j++){
        for(i = 0;i < n;i++){
            ord[i] = i*m+j;
        }
        sort(ord,ord+n,cmp);
        for(i = 1;i < n;i++){
            if(a[ord[i-1]]==a[ord[i]]) unite(ord[i],ord[i-1]);
        }
    }
}
void sol(){
    int i,j,u,v;
    for(i = 0;i < V;i++) if(find(i)==i&°[i]==0) que.push(i);
    while(!que.empty()){
        u = que.front();que.pop();
        for(i = E[u];i != -1;i = buf[i].next){
            v = buf[i].b;
            d[v] = max(d[v],d[u]+1);
            if(--deg[v]==0){
                que.push(v);
            }
        }
    }
    for(i = 0;i < V;i++){
        printf("%d ",d[find(i)]+1);
        if((i+1)%m==0) putchar('\n');
    }
}

int main(){
    int i,j;
    scanf("%d%d",&n,&m);
    init();
    for(i = 0;i < n*m;i++) scanf("%d",&a[i]);
    pre_preocess();
    for(i = 0;i < n;i++){
        for(j = 0;j < m;j++){
            ord[j] = i*m+j;
        }
        sort(ord,ord+m,cmp);
        for(j = 1;j < m;j++){
            if(a[ord[j-1]]==a[ord[j]]) continue;
            add_edge(find(ord[j-1]),find(ord[j]));
        }
    }
    for(j = 0;j < m;j++){
        for(i = 0;i < n;i++){
            ord[i] = i*m+j;
        }
        sort(ord,ord+n,cmp);
        for(i = 1;i < n;i++){
            if(a[ord[i-1]]==a[ord[i]]) continue;
            add_edge(find(ord[i-1]),find(ord[i]));
        }
    }
    sol();
    return 0;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:36723次
    • 积分:2553
    • 等级:
    • 排名:第14835名
    • 原创:228篇
    • 转载:8篇
    • 译文:0篇
    • 评论:1条
    文章分类