1. 程式人生 > >資訊學奧賽一本通(C++版) 第三部分 資料結構 第三章 樹

資訊學奧賽一本通(C++版) 第三部分 資料結構 第三章 樹

//1336 【例3-1】找樹根和孩子
//提交,未通過,明白了,孩子必須按字典序輸出
//修改,提交,AC 2017-12-13 18:54
//該題思路可以預計,與書中提供的程式碼很不相同,書中猜測用的是左子右兄表示法,日後驗證
//該題,本人思路,鄰接表,有向圖.
//很明顯,水平上了一個臺階。
#include <stdio.h>
#include <string.h>
int parent[110],head[110],cnt=0,d[110];//parent[i]節點i的父親,d[i]儲存max的孩子
struct node{
    int to,next;
}e[210];//有向圖
void add_edge(int u,int v){
    cnt++,e[cnt].to=v,e[cnt].next=head[u],head[u]=cnt;
}
int main(){
    int x,y,n,m,i,max=0,b,count,j,t;
    memset(parent,0,sizeof(parent));
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        parent[y]=x,add_edge(x,y);
    }
    for(i=1;i<=n;i++)//找root
        if(parent[i]==0)printf("%d\n",i);
    for(i=1;i<=n;i++){//找孩子最多的節點
        count=0;
        for(b=head[i];b;b=e[b].next)
            count++;
        if(count>max)max=count,j=i;
    }
    count=0;
    for(b=head[j];b;b=e[b].next)d[count++]=e[b].to;//儲存孩子
    printf("%d\n",j);
    for(i=0;i<count;i++)//自小到大排序
        for(j=i+1;j<count;j++)
            if(d[i]>d[j])t=d[i],d[i]=d[j],d[j]=t;
    for(i=0;i<count;i++)printf("%d ",d[i]);
    return 0;
}
//1337 【例3-2】單詞查詢樹
//首先明確,是一棵樹,而不是二叉樹
//第一直覺是採用樹的處理方式,至少是遞迴
//無奈,眼高手低,
//搜尋網路,https://www.cnblogs.com/sssy/p/6640480.html此文程式碼寫得不錯,雖然沒有什麼說明,但還是看懂程式碼了
//經檢驗,上述程式碼AC,可以開始獨立編寫了
//樣例通過,提交 測試點4 答案錯誤
//靜態閱讀程式碼,發現 漏了 讀入的字串 排序
//新增,提交,AC 2017-12-19 18:40
#include <stdio.h>
#include <string.h>
char a[32000][70];
void quicksort(int left,int right){//字串處理的快排,自小到大排序
    int i=left,j=right,mid=(left+right)/2;
    char b[70];
    while(i<=j){
        while(strcmp(a[i],a[mid])<0)i++;
        while(strcmp(a[mid],a[j])<0)j--;
        if(i<=j){
            strcpy(b,a[i]);
            strcpy(a[i],a[j]);
            strcpy(a[j],b);
            i++,j--;
        }
    }
    if(i<right)quicksort(i,right);
    if(left<j)quicksort(left,j);
}
int main(){
    int ans,i=0,j,len;
    while(scanf("%s",a[i])!=EOF)i++;//字串序列讀取,序列從0開始
    len=i;
    quicksort(0,len-1);//遺漏此句 ,測試點4 答案錯誤
    ans=strlen(a[0]);
    for(i=1;i<len;i++){
        j=0;
        while(a[i-1][j]==a[i][j])j++;//查尋雷同部分
        ans+=strlen(a[i])-j;//不同部分,就需開新節點來儲存
    }
    ans+=1;//加上root元素
    printf("%d",ans);
    return 0;
}

//1338 【例3-3】醫院設定
//https://www.cnblogs.com/harden/p/5596801.html看了文中才明白,要用Floyd演算法,想象與現實差距太大
//樣例通過,提交AC 2017-12-20
#include <stdio.h>
#include <string.h>
#define INF 999999999
int a[110][110],b[110],d[110];
int main(){
    int i,j,n,k,left,right,min=INF;//此處寫成 min=0 昏招
    memset(d,0,sizeof(d));
    scanf("%d",&n);
    for(i=1;i<=n;i++)//矩陣初始化
        for(j=1;j<=n;j++)
            if(i==j)a[i][j]=0;
            else a[i][j]=INF;
    for(i=1;i<=n;i++){
        scanf("%d%d%d",&b[i],&left,&right);
        if(left!=0)a[i][left]=a[left][i]=1;//無向圖
        if(right!=0)a[i][right]=a[right][i]=1;
    }
    for(k=1;k<=n;k++)//Floyd演算法
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
                if(a[i][j]>a[i][k]+a[k][j])
                    a[i][j]=a[i][k]+a[k][j];
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            d[i]+=a[i][j]*b[j];
    for(i=1;i<=n;i++)
        if(d[i]<min)
            min=d[i];
    printf("%d",min);
    return 0;
}


//1339 【例3-4】求後序遍歷
//樣例通過,提交,測試點3-5 答案錯誤
//急尋測試資料
//提供一組測試資料
//輸入資料
//abdcef
//bdaecf
//輸出資料
//dbefca
//核心,先序字串對應先序字串,中序字串對應中序字串
//筆誤造成排查很久,for(i=len2+1;i<len1;i++)e[i-(len2+1)]=a[i];//此處寫成 e[i-(len2+1)]=b[i] 昏招,修改,提交AC 2017-12-14
#include <stdio.h>
#include <string.h>
char pre[100],in[100];
void PostOrder(char *a,char *b){//a先序 b中序
    char c[100],d[100],e[100],f[100];//c先序 d中序 e先序 f中序