zoj 3761

很简单但很虐心的一道题;

我感觉自己的算法没错,但是老是过不了;= =

但是还是把代码贴出来;

我的方法,用并查集的方式做一课树,然后对树进行遍历;

有多少棵树就有多少个点剩余;

#include<cstdio>
#include<algorithm>
#include<cstring>
#define inf 1000000000
#define maxn 2009
using namespace std;

struct node
{
    int x;
    int y;
    int p;
    int sum;
    int son[5];
    bool operator <(const node &t)const
    {
        if(x==t.x)
            return y<t.y;
        else return x<t.x;
    }
} no[maxn];

int f[maxn];
int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]);
}

int dis(int a,int b)
{
    return(abs(no[a].x-no[b].x)+abs(no[a].y-no[b].y));
}

bool check(int a,int b)
{
    bool flag=1;
   if(no[a].x!=no[b].x&&no[a].y!=no[b].y)
        flag=0;
    if(find(b)==a)flag=0;
    if(no[b].sum>=4)flag=0;
    return flag;
}

void dfs(int root)
{
    for(int i=0;i<no[root].sum;i++)
        dfs(no[root].son[i]);
    if(no[root].p!=-1)
    {
       if(no[root].x==no[no[root].p].x)
        {
           if(no[root].y<no[no[root].p].y)
            {
               printf("(%d, %d) UP
",no[root].x,no[root].y);
            }
            else printf("(%d, %d) DOWN
",no[root].x,no[root].y);
        }
        else if(no[root].y==no[no[root].p].y)
        {
           if(no[root].x<no[no[root].p].x)
               printf("(%d, %d) RIGHT
",no[root].x,no[root].y);
            else printf("(%d, %d) LEFT
",no[root].x,no[root].y);
        }
    }
}

int main()
{
    int n;
    int tar,d;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0; i<n; i++)
        {
           scanf("%d%d",&no[i].x,&no[i].y);
            no[i].p=-1;
            f[i]=i;
            no[i].sum=0;
        }
        for(int i=0; i<n; i++)
        {
            d=inf;
            tar=-1;
            for(int j=0; j<n;j++)
            {
               if(i==j) continue;
               if(dis(i,j)<d&&check(i,j))
               {
                   d=dis(i,j);
                   tar=j;
               }
            }
           if(tar==-1){no[i].p=-1;continue;}
            no[i].p=tar;
            f[i]=tar;
            no[tar].son[no[tar].sum++]=i;
        }
        int ans=0;
        for(int i=0; i<n; i++)
           if(no[i].p==-1)
               ans++;
        printf("%d
",ans);
        for(int i=0; i<n; i++)
        {
            if(no[i].p==-1)
               dfs(i);
        }
    }
    return 0;
}
/*
18
1 1
2 1
2 2
4 2
5 2
6 2
2 3
3 3
4 3
5 3
7 3
5 4
8 4
1 5
2 5
3 5
4 5
5 5
*/
View Code

感谢文蔚大叔给我出了一组数据,让我意识到自己的算法的缺陷;

我先前的做法是构造一棵树,但是发现用贪心的方法建树的时候可能会把本来的一棵树变成两棵树,这样的话就错了;

所以我后来改成一个图,然后再图中dfs,这样的话就没错了;

#include<cstdio>
#include<cstring>
#define maxn 2009
#include<algorithm>
#define inf 1e9
using namespace std;
char s[4][10]={"LEFT","DOWN","RIGHT","UP"};
struct node
{
    int x,y;
    int son[4];
    int d[4];
} no[maxn];
bool vis[maxn];
int f[maxn];

int check(int a,int b)
{
    return (abs(no[a].x-no[b].x)+abs(no[a].y-no[b].y));
}

int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]);
}

void un(int x,int y)
{
    int a=find(x);
    int b=find(y);
    if(a!=b)
        f[a]=b;
    return;
}

void dfs(int x,int f)
{
    vis[x]=1;
    for(int i=0;i<4;i++)
    {
        int v=no[x].son[i];
        if(v!=-1&&!vis[v])
        {
            dfs(v,x);
        }
    }
    if(f!=-1)
    {
        for(int i=0;i<4;i++)
        {
            if(no[f].son[i]==x)
            {
                printf("(%d, %d) %s
",no[x].x,no[x].y,s[i]);
            }
        }
    }
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0; i<n; i++)
        {
            scanf("%d%d",&no[i].x,&no[i].y);
            for(int j=0; j<4; j++)
            {
                no[i].son[j]=-1;
                no[i].d[j]=inf;
                f[i]=i;
            }
        }
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<n; j++)
            {
                if(i==j)continue;
                if(no[i].x==no[j].x)
                {
                    un(i,j);
                    if(no[j].y<no[i].y)
                    {
                        if(check(i,j)<no[i].d[3])
                        {
                            no[i].son[3]=j;
                            no[i].d[3]=check(i,j);
                        }
                    }
                    else
                    {
                        if(check(i,j)<no[i].d[1])
                        {
                            no[i].son[1]=j;
                            no[i].d[1]=check(i,j);
                        }
                    }
                }
                else if(no[i].y==no[j].y)
                {
                    un(i,j);
                    if(no[j].x<no[i].x)
                    {
                        if(check(i,j)<no[i].d[2])
                        {
                            no[i].son[2]=j;
                            no[i].d[2]=check(i,j);
                        }
                    }
                    else
                    {
                        if(check(i,j)<no[i].d[0])
                        {
                            no[i].son[0]=j;
                            no[i].d[0]=check(i,j);
                        }
                    }
                }
            }
        }
        int ans=0;
        for(int i=0;i<n;i++)
        {
            if(f[i]==i)
                ans++;
        }
        printf("%d
",ans);
        memset(vis,0,sizeof vis);
        for(int i=0;i<n;i++)
        {
            dfs(i,-1);
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/yours1103/p/3577505.html