交换卡片

来源:互联网 发布:js删除disabled属性 编辑:程序博客网 时间:2024/04/27 20:16

FJNU.1965

Description
小明是一个对计算机有着浓厚兴趣的初中生,暑假期间参加了学校组织的信息学夏令营。在老师的指导下,小明学到了很多计算机知识,不知不觉,渡过了一个令人难忘的夏令营。在夏令营结束的那天,老师让大家一起做一个换卡片的游戏,给每人发一张双面都写有一个数字的卡片,并且为每人指定一个幸运数字,这个数字一定会出现在某张卡片上。并要求大家通过与其他同学交换卡片,来获得一张包含自己幸运数字的卡片。交换的规则是,两张卡片至少有一个数字是相同的时候才能进行交换。老师让每位同学以最少的交换次数拿到包含自己幸运数字的卡片。请你帮小明算算,他最少要交换多少次才能获得那张包含他的幸运数字的卡片。

Input
输入的第一行含一个正整数k,表示测试例个数。下面紧接着k个测试例的数据。每个测试例数据的第一行含一个正整数N(N<=50000),表示卡片的数量;随后的一行包含一个正整数,表示老师指定给小明的幸运数字;紧接下来的N行每行由2个整数组成(整数取值的范围为1~50000),分别表示每张卡片两面上的数字。其中第一行的两个整数,即为发给小明的卡片上的两个整数。同一行的数据之间用一个空格隔开,两个测试例之间用一个空行隔开。

Output
对应每个测试例输出一个整数,表示卡片的最少交换次数,如果无解,则输出-1。一个整数占一行。

Sample Input
2
7
6
1 2
2 3
1 3
3 4
6 2
4 6
2 6

6
5
1 3
5 2
3 4
6 3
1 4
6 1

Sample Output
1
-1

Source
福建师范大学第五届程序设计竞赛

My Program

#include<iostream>
#define N 50005
using namespace std;

typedef 
struct CARD
{
    
int num;
    
struct CARD *next;
}
card;

int main()
{
    
int front,rear,queue[N];
    
int i,k,n,t,a,b,s1,s2,h[N];
    card c[N],
*p;
    cin
>>k;
    
while(k--)
    
{
        cin
>>n;
        cin
>>t;
        
for(i=0;i<N;i++)
        
{
            h[i]
=0;
            c[i].next
=NULL;
        }

        front
=0;rear=1;
        scanf(
"%d%d",&a,&b);
            p
=new card;
            p
->num=b;
            p
->next=NULL;
            c[a].next
=p;
            p
=new card;
            p
->num=a;
            p
->next=NULL;
            c[b].next
=p;
        s1
=a;s2=b;
        queue[front]
=t;
        
for(i=1;i<n;i++)
        
{
            scanf(
"%d%d",&a,&b);
            p
=new card;
            p
->num=b;
            p
->next=c[a].next;
            c[a].next
=p;
            p
=new card;
            p
->num=a;
            p
->next=c[b].next;
            c[b].next
=p;
        }

        
while(front<rear)
        
{
            t
=queue[front];
            
if(t==s1||t==s2)
                
break;
            p
=c[t].next;
            
while(p!=NULL)
            
{
                
if(h[p->num]==0)
                
{
                    queue[rear
++]=p->num;
                    h[p
->num]=h[t]+1;
                }

                p
=p->next;
            }

            front
++;
        }

        
if(t!=s1&&t!=s2)
            printf(
"-1/n");
        
else
            printf(
"%d/n",h[t]);
    }

    
return 0;
}

YOYO's Note:
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄它是华丽的分隔线

【题意简述】

有N张卡片,每张卡片上有两个数字,当两个数字中的任一数字与其他卡片相同时就可以交换卡片。我们的目的是通过最少的交换次数换到有幸运数字的卡片。


【粗略分析】

比较明显的,无向图求点到点的最短路径(?我不知道怎么说)。
为了查找方便,用链表形式存储无向图,每张卡片我都存两边,
然后从幸运数字开始倒回来用BFS搜索,同时记录第一次访问到时交换的次数,
当找到初始时的两个数字中的任一个或搜索完成时结束。

【C++源代码】

#include<iostream>
#define N 50005
using namespace std;

typedef 
struct CARD
{
    
int num;
    
struct CARD *next;
}
card;

int main()
{
    
int front,rear,queue[N];
    
int i,k,n,t,a,b,s1,s2,h[N];
    card c[N],
*p;
    cin
>>k;
    
while(k--)
    
{
        cin
>>n;
        cin
>>t;
        
for(i=0;i<N;i++)
        
{
            h[i]
=0;
            c[i].next
=NULL;
        }

        front
=0;rear=1;
        scanf(
"%d%d",&a,&b);
            p
=new card;
            p
->num=b;
            p
->next=NULL;
            c[a].next
=p;
            p
=new card;
            p
->num=a;
            p
->next=NULL;
            c[b].next
=p;
        s1
=a;s2=b;
        queue[front]
=t;
        
for(i=1;i<n;i++)
        
{
            scanf(
"%d%d",&a,&b);
            p
=new card;
            p
->num=b;
            p
->next=c[a].next;
            c[a].next
=p;
            p
=new card;
            p
->num=a;
            p
->next=c[b].next;
            c[b].next
=p;
        }

        
while(front<rear)
        
{
            t
=queue[front];
            
if(t==s1||t==s2)
                
break;
            p
=c[t].next;
            
while(p!=NULL)
            
{
                
if(h[p->num]==0)
                
{
                    queue[rear
++]=p->num;
                    h[p
->num]=h[t]+1;
                }

                p
=p->next;
            }

            front
++;
        }

        
if(t!=s1&&t!=s2)
            printf(
"-1/n");
        
else
            printf(
"%d/n",h[t]);
    }

    
return 0;
}

【注意事项】

※ 好象没什么好注意的……这题好象很容易超时,记得大数据量的时候用scanf/printf..


【点评】

可以算是数据结构里图论的入门题吧。。

原创粉丝点击