1. 程式人生 > >Hdu 2094之解題報告

Hdu 2094之解題報告


Problem Description 有一群人,打乒乓球比賽,兩兩捉對撕殺,每兩個人之間最多打一場比賽。
球賽的規則如下:
如果A打敗了B,B又打敗了C,而A與C之間沒有進行過比賽,那麼就認定,A一定能打敗C。
如果A打敗了B,B又打敗了C,而且,C又打敗了A,那麼A、B、C三者都不可能成為冠軍。
根據這個規則,無需迴圈較量,或許就能確定冠軍。你的任務就是面對一群比賽選手,在經過了若干場撕殺之後,確定是否已經實際上產生了冠軍。

Input 輸入含有一些選手群,每群選手都以一個整數n(n<1000)開頭,後跟n對選手的比賽結果,比賽結果以一對選手名字(中間隔一空格)表示,前者戰勝後者。如果n為0,則表示輸入結束。

Output 對於每個選手群,若你判斷出產生了冠軍,則在一行中輸出“Yes”,否則在一行中輸出“No”。

Sample Input 3 Alice Bob Smith John Alice Smith 5 a c c d d e b e a d 0
Sample Output Yes No

法一:(鄰接表)

#include<stdio.h>
#include<string.h>
int top,cnt,flag;
struct Edge{
    int n;// 入度
    char s[10];
    Edge *next;
    Edge(int nn=0):n(nn){}
}*head[1010],e1[1010],e[1010];
void Addedge(char *s1,char *s2,int n){
    flag=0;
    Edge *p=&e[top++];
    strcpy(p->s,s2);
    for(int i=0;i<cnt;i++){//對頭結點進行查詢,查詢相同的頭結點
         Edge *pp=head[i];
         if(strcmp(pp->s,s1)==0){
             p->next=pp->next;
             pp->next=p;
             flag=1;
             break;
         }
    }
    if(!flag){//沒有找到相同的頭結點,新增
        Edge *q=&e1[cnt];
        strcpy(q->s,s1);
        p->next=head[cnt];
        head[cnt]=q;
        q->next=p;
        for(int i=0;i<cnt;i++){//在當前所有的鄰接表中查詢新增的頭結點是否在別的鄰接表中的,在的話說明這個新增的結點雖然當前這組關係中是贏的人,但在之前的關係中,他是輸的人
            for(Edge *p=head[i];p;p=p->next){
                if(strcmp(p->s,s1)==0)
                    q->n++;//他對應的入度加1;
            }
        }
        cnt++;
    }
    for(int i=0;i<cnt;i++){//關係處理後,進行之前所有頭結點的入度重新判斷,在新增的關係中,s2是輸的人,有可能在之前的關係中是贏的人,那麼就把之前的關係中相應的入度加1,
        Edge *pp=head[i];
            if(strcmp(pp->s,s2)==0)
                pp->n++;
    }
}
int main(){
    int n;
    while(~scanf("%d",&n),n){
        memset(head,0,sizeof(head));
        memset(e1,0,sizeof(e1));//用來新增頭結點取實際位置,每組資料輸入一定要清0,不然會WA
        top=0,cnt=0;
        int ans=0;
        char s1[50],s2[50];
        for(int i=0;i<n;i++){
            scanf("%s%s",s1,s2);
            Addedge(s1,s2,n);
        }
        for(int i=0;i<cnt;i++){//判斷頭結點有幾個入度為0的
            Edge *p=head[i];
            if(p->n==0)
                ans++;
        }
        if(ans==1)
            printf("Yes\n");
        else printf("No\n");
    }
}

法二:

程式碼:

#include<stdio.h>
#include<string.h>
char win[1010][20],lose[1010][20];
int visit[1010];
int main(){
    int n;
    while(~scanf("%d",&n),n){
        int sum=0;
        for(int i=0;i<n;i++){
            scanf("%s%s",win[i],lose[i]);
            visit[i]=1;
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(strcmp(win[i],lose[j])==0)
                    visit[i]=0;
                if(i!=j&&strcmp(win[i],win[j])==0)
                    visit[j]=0;
            }
            sum+=visit[i];
        }
        if(sum==1)
            printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}