codeforces 650c

求最长路,相同的点用并查集缩点。。 不得不吐槽下这个博客,退出按键找了半天,重新登录这个号后,发表文章还是显示的那个号。本来写好了的题解,一下就没了,懒得重写了。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<string.h>
using namespace std;
#define maxn 1000005

int n,m;
struct node
{
    int x,y,w,id;
    node(int x=0,int y=0,int w=0,int id=0):x(x),y(y),w(w),id(id){}
    friend bool operator<(const node x,const node y)
    {
        return x.w<y.w;
    }
};
struct node a[maxn];
struct edge
{
    int en,next;
}E[maxn*6];
int p[maxn],fa[maxn],dis[maxn],vis[maxn];
int num;
void init()
{
    memset(p,-1,sizeof(p));
    num=0;
}
void add(int st,int en)
{
    E[num].en=en;
    E[num].next=p[st];
    p[st]=num++;
}
int findfa(int x)
{
    if(x==fa[x])
        return x;
   return fa[x]=findfa(fa[x]);
}
void dfs(int id)
{
    vis[id]=1;
    dis[id]=0;
    for(int i=p[id];i!=-1;i=E[i].next)
    {
        int en=E[i].en;
        if(!vis[en])
        {
            dfs(en);
            dis[id]=max(dis[id],dis[en]+1);
        }
        else dis[id]=max(dis[id],dis[en]+1);
    }

}
vector<node>v[maxn];//用于行
vector<node>v2[maxn];//用于列
int main()
{

    int cnt,i,j;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        for(i=0;i<=n;i++)
        {
            v[i].clear();
            v2[i].clear();
        }
        cnt=0;
        for(i=0;i<n;i++)
        {
            for(j=0;j<m;j++)
            {
                int x;
                scanf("%d",&x);
                ++cnt;
                a[cnt]=node(i,j,x,cnt);
                v[i].push_back(node(i,j,x,cnt));
            }
        }
        for(i=0;i<=cnt;i++)
            fa[i]=i;
        for(i=0;i<n;i++)
        {
            sort(v[i].begin(),v[i].end());//排序
            for(j=1;j<m;j++)
            {
                if(v[i][j].w==v[i][j-1].w)
                {
                    int tx=findfa(v[i][j-1].id);
                    int ty=findfa(v[i][j].id);
                    fa[ty]=tx;//并查集缩点
                }
            }
        }
        for(i=0;i<m;i++)
        {
            for(j=0;j<n;j++)
            {
                v2[i].push_back(a[j*m+i+1]);
            }
        }

        for(i=0;i<m;i++)
        {
            sort(v2[i].begin(),v2[i].end());
            for(j=1;j<n;j++)
            {
                if(v2[i][j].w==v2[i][j-1].w)
                {
                    int tx=findfa(v2[i][j-1].id);
                    int ty=findfa(v2[i][j].id);
                    fa[ty]=tx;
                }
            }
        }
        for(i=0;i<n;i++)
        {
            for(j=1;j<m;j++)
            {
                if(v[i][j].w!=v[i][j-1].w)
                {
                    int tx=findfa(v[i][j-1].id);
                    int ty=findfa(v[i][j].id);
                    add(ty,tx);//行建边
                }
            }
        }
        for(i=0;i<m;i++)
        {
            for(j=1;j<n;j++)
            {
                 if(v2[i][j].w!=v2[i][j-1].w)
                {
                    int tx=findfa(v2[i][j-1].id);
                    int ty=findfa(v2[i][j].id);
                    add(ty,tx);//列建边
                }
            }
        }
        memset(dis,0,sizeof(dis));
        memset(vis,0,sizeof(vis));
        /*for(i=1;i<=12;i++)
        {
            printf("%d ",fa[i]);

        }
        printf("*** \n");*/
        for(i=1;i<=cnt;i++)
        {
            int tx=findfa(i);
            if(!vis[tx])
            {

                dfs(tx);//找最长路 用dis记录
            }
        }
        //cout<<dis[1]<<endl;
        for(i=0;i<n;i++)
        {
            for(j=0;j<m;j++)
            {
                int ans=dis[findfa(a[(i)*m+j+1].id)];
                printf("%d",ans+1);
                if((j+1)!=m)
                    printf(" ");
                else puts("");
            }
        }
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值