之前紫书的树学的比较乱,只顾着做题。现在从新学一下树这种数据结构。
poj1330
练习一下用双亲数组存储树,和遍历树。
这个题只要一条路走到根位置,把走过的位置标记就行,然后判断另一条是否经过这个点。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=10000+10;
int a[maxn];
int t,n;
bool vis[maxn];
int main()
{
//freopen("in.txt","r",stdin);
cin>>t;
while(t--)
{
int x,y;
cin>>n;
memset(a,0,sizeof(a));
memset(vis,false,sizeof(vis));
for(int i=0;i<n-1;++i)
{
cin>>x>>y;
a[y]=x;
}
cin>>x>>y;
while(y!=0)
{
vis[y]=true;
y=a[y];
}
while(!vis[x])
{x=a[x];}
cout<<x<<endl;
}
return 0;
}
poj2499
思路:因为二叉树到所有节点的路径是唯一的,所以我们可以从节点出发,依次向着根走。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int t,kase=0;
int main()
{
cin>>t;
while(t--)
{
int a,b,right=0,left=0;
cin>>a>>b;
int temp;
while(a!=1||b!=1)//这里是或
{
if(a>b)
{
temp=(a-1)/b;//数据规模较大,一次减除来,因为根节点是(1,1)所以a-1,下面同理。
a-=(b*temp);
left+=temp;
}else
{
temp=(b-1)/a;
b-=a*temp;
right+=temp;
}
}
printf("Scenario #%d:\n%d %d\n\n",++kase,left,right);
}
return 0;
}
poj2255
二叉树的遍历
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
char a[30],b[30];
int L1,R1,L2,R2;
vector<char>ans;
void tree(int L1,int R1,int L2,int R2)
{
if(L1>R1)return ;
int k=0;
while(a[L1]!=b[L2+k])k++;
tree(L1+1,L1+k,L2,L2+k-1);
tree(L1+k+1,R1,L2+k+1,R2);
ans.push_back(a[L1]);
}
int main()
{
//freopen("in.txt","r",stdin);
while(cin>>a>>b)
{
ans.clear();
L1=strlen(a);
tree(0,L1-1,0,L1-1);
for(int i=0;i<ans.size();++i)
cout<<ans[i];
cout<<endl;
}
return 0;
}
poj2309
思路:注意观察图中树的特点。
1如果x为奇数,则是单独节点。
2如果x为偶数,则最底层的数字在[x-2^k+1,x-1][x+1,x+2^k-1]。其中2^k可以用x&(-x)计算出来,涉及到负数的二进制表示。
#include <iostream>
#include <cstdio>
using namespace std;
int t,x,k;
int main()
{
cin>>t;
while(t--)
{
cin>>x;
k=x&(-x);
cout<<x-k+1<<" "<<x+k-1<<endl;
}
return 0;
}
zoj2724
二叉堆,根节点小于(大于)叶节点,采用优先队列。注意结构体和strcmp的使用
数据量比较大,建议改成scanf和printf.
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <iostream>
using namespace std;
struct message
{
char name[100];
int data;
int priority;
bool operator <(const message &a) const
{
return a.priority<priority;
}
};
priority_queue<message>q;
char cmd[100];
message m;
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%s",&cmd)!=EOF)
{
if(strcmp(cmd,"GET")==0)
{
if(!q.size())cout<<"EMPTY QUEUE!\n";
else
{
cout<<q.top().name<<" "<<q.top().data<<endl;
q.pop();
}
}
else if(strcmp(cmd,"PUT")==0)
{
cin>>m.name>>m.data>>m.priority;
q.push(m);
}
}
return 0;
}
poj3253
哈夫曼树 权值*路径之和最低 此处采用优先队列。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
priority_queue<int,vector<int>,greater<int> >q;
int main()
{
int n,temp;
while(cin>>n)
{
while(!q.empty())q.pop();
for(int i=0;i<n;++i)
{
cin>>temp;
q.push(temp);
}
int a,b;
long long ans=0;
while(q.size()>1)
{
a=q.top();q.pop();
b=q.top();q.pop();
ans+=(a+b);
q.push(a+b);
}
cout<<ans<<endl;
}
return 0;
}