Uvaoj 10763详解+思想(不只是题的思想)

UvaOJ 10763


  

 题目意思很明确:就是输入一组数,看是否能成对,1 2 和 2 1这样的。(If a student wants to go from A to B, there must be another student who wants to go from B to A. )

   

 我看到有人是这样写的代码,我非常不解!什么情况,这也能通过么?(的确是通过了),但是如果我输入这样一组数:

  4

  1 2

  2 4

  2 1

  4 2

  0

那么正确答案应该是YES ,若是这样代入下面这个代码,,那么答案是NO! ( 1 2 和 2 4 交叉到了)

类似然而这样的代码非常多,希望大家不要因为某些代码通过 而不去质疑是否真的正确。。

#include<iostream>         //erroy  但是这个代码可以通过,,,,

#include<cstdio>

const int MAXN = 500005;  
int arr[MAXN];  
void init_arr() {  
    for (int i = 0; i < MAXN; i ++) {  
        arr[i] = i;  
    }  
}  
void swap_arr (int a, int b) {  
    int t = arr[a];  
    arr[a] = arr[b];  
    arr[b] = t;  
}  
bool isOk() {  
    for (int i = 0; i < MAXN; i ++) {  
        if (arr[i] != i) {  
            return false;  
        }  
    }  
    return true;  
}  
int main() {  
    int n;  
    int a, b;  
    while (scanf("%d", &n) != EOF) {  
        getchar();  
        if (n == 0) break;  
        init_arr();  
        for (int i = 0; i < n; i ++) {  
            scanf("%d%d", &a, &b);  
            swap_arr(a, b);  
        }  
        if (isOk()) {  
            printf("YES\n");  
        } else {  
            printf("NO\n");  
        }  
    }  
    return 0;  
}  



----------------------------------------------------------------------------------------------------------------------

 但是这个思路是很好的!不过需要稍作改进!  

  影响答案的结果是这个顺序的问题,如果排序后为

  1 2

  2 1

  2 4

  4 2

  再带进检测,那么答案就OK了!

--------------------------------------------------------------------------------------------------

  问题来了,怎么排,我有一个解决排序的方法:

  在这里设置了一个结构体,如果输入两个数之和相等就排在一起解决 ,将1 2 与2  4 分开关系!

  由于不可能出现和相等,数字还能进行交叉的情况,所以这个方法可行

  这个题缺少不了排序的问题


  还要考虑排序用哪个,对于50000这样的数 O(n平方)已经支撑不了了(那么冒泡,选择排序就不要想了)

可以选用有分治思想的 快排,归并排,(堆排序就算了吧,写着麻烦)这些都是O(nlog n)


  这题是有难度的,好好练习排序。

--------------------------------------------------------------------------------------------------

AC了 ,哦耶!

#include<stdio.h>
typedef struct 
{
int beg;
        int end;
int sum;
}stu;
stu st[500000];
stu st1[500000];
int sort(int l , int h)  //用的是归并排序 Nlog2 N  可以应对10的六次方个数,所以大胆的用!
{

   if(h-l<=1)return 0; 
   int i,mid = (l+h)/2;
   sort(l,mid);
   sort(mid,h);
   int j = mid;
   int k =0;
   i = l;
   while(i<mid  &&  j<h)
   {
  if(st[i].sum <st[j].sum)
  {st1[k++] = st[i++];}
  else if(st[i].sum > st[j].sum )
  {st1[k++] = st[j++];}
  else
  {
  if(st[i].beg <=st[j].beg )
  {
  st1[k++] = st[i++];
  }
  else
  {
  st1[k++] = st[j++];
  }
 
  }


   }
   
   for(;j<h;j++)
st1[k++]=st[j];    
   for(;i<mid;i++)
   st1[k++]=st[i];
   k=0;
   for(i=l;i<h;i++)
st[i] = st1[k++];

}
int c[500000];
int main()
{
int n,i;
    while(1)
{
   scanf("%d",&n);
if(n==0)break;
       
for(i=0;i<n;i++)
{
scanf("%d %d",&st[i].beg,&st[i].end);
st[i].sum  = st[i].beg + st[i].end ;
}
if(n%2==0)
{


    sort(0,n);
   int t;
   for(i=0;i<n;i++)
c[i]=i;
for(i=0;i<n;i++)
               {
        t = c[st[i].beg];
        c[st[i].beg] = c [st[i].end];
        c [st[i].end] = t;
}
for(i=0;i<n;i++)
if(c[i] != i)break;

if(i==n)printf("YES\n");
else printf("NO\n");

}
        else  printf("NO\n");

}

return 0;
}

你可能感兴趣的:(c,归并排序,学会去质疑他人已经通过的代码)