题目链接:
题意:
先给出N个节点的出现次数
再给出M种编码方式
判断每种编码方式是否能构成哈夫曼树
题解:
判断哈夫曼编码的条件有两个:
1 哈夫曼编码不唯一,但它的WPL(带权路径长度)一定唯一
2 短码不能是长码的前缀
首先可以使用STL优先队列 根据 WPL=所有非叶节点的权值之和 求出标准的WPL1
再根据WPL2=所有叶节点的高度*权值之和
再单独判断是否编码中构成前缀
两个条件都满足则输出Yes
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; struct node1{ char ch; int num; }aa[105]; struct node2{ char ch; string str; }bb[105]; int n; int cmp(node2 a,node2 b){ return a.str.size()<b.str.size(); } int pos(char a) { for(int i=1;i<=n;i++) if(aa[i].ch==a) return i; } int judge(){ //判断是否有前缀 sort(bb+1,bb+1+n,cmp); for(int i=1;i<=n;i++){ string t=bb[i].str; for(int j=i+1;j<=n;j++) if(bb[j].str.substr(0,t.size())==t) return 1; } return 0; } int main(){ int m,ans1=0,ans2; scanf("%d",&n); priority_queue< int,vector<int>,greater<int> >q; for(int i=1;i<=n;i++) { cin>>aa[i].ch>>aa[i].num; q.push(aa[i].num); } int a,b; while(!q.empty()){ a=q.top(); q.pop(); if(!q.empty()){ //最后队列中只会剩下一个根节点 b=q.top(); q.pop(); q.push(a+b); } ans1+=a+b; } ans1=ans1-a-b; // WPL=所有非叶节点的权值之和 scanf("%d",&m); while(m--){ ans2=0; for(int i=1;i<=n;i++){ cin>>bb[i].ch>>bb[i].str; ans2+=aa[pos(bb[i].ch)].num*bb[i].str.size(); //WPL2=所有叶节点的高度*权值之和 } if(ans2!=ans1) cout<<"No"<<endl; else if(judge()) cout<<"No"<<endl; else cout<<"Yes"<<endl; } return 0; }
时间: 2024-11-18 01:08:39