分析
这道题细节很多:)
对于total,能够直接想到的就是枚举树根,有几个点没有父亲就有几棵树。
对于求第几代学生,其实就相当于BFS将图分层, f f f数组记录就行: f [ e [ i ] . t o ] . s = f [ q [ h ] ] . s + 1 f[e[i].to].s=f[q[h]].s+1 f[e[i].to].s=f[q[h]].s+1
但是这题的细节处理很关键:
- 一开始对于字符串的提取和存储。将36个字符转化为1~36作为结点的下标,并且记录哪个字符出现过,后面要跳过没出现过的字符不做处理。
- 输出的时候要用一个 t t t结构体替代 f f f结构体。结构体的两个域分别存自己的层数和原本的下标,因为要按层数排序,下标记录便于输出。然而 f f f 结构体不能被改变,所以要复制一个来输出。输出要按照格式搞,第一个单独输出,后面与前面不一样的输出一个“,”
- 另外,对于“NO answer!”的判断,其实就是一棵树上存不存在环,如果很多棵树只有环,才是没有答案,一开始的程序这里出现问题被hack了。
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
struct node
{
int to,next;
}e[100010];
struct donkey
{
int s,p;
}f[100010];
struct donkeycpy
{
int s,p;
}t[100010];
int n,cnt,ff,fff,bz;
int v[100010],fa[100010],ap[100010];
int hd[100010],tot;
void add(int x,int y)
{
e[++tot]=(node){y,hd[x]};
hd[x]=tot;
}
int cmp(donkeycpy l,donkeycpy r)
{
if(l.s==r.s) return l.p<r.p;
else return l.s<r.s;
}
bool reach(int x,int start,int target)
{
for(int i=hd[x];i;i=e[i].next)
{
if(bz) return true;
if(e[i].to==target||e[i].to==start)
{
bz=1;
return true;
}
reach(e[i].to,start,target);
}
}
void bfs(int st)
{
queue<int> q;
v[st]=1;
f[st].s=1;
q.push(st);
while(!q.empty())
{
int x=q.front();
q.pop();
v[x]=1;
for(int i=hd[x];i;i=e[i].next)
{
bz=0;
if(reach(e[i].to,e[i].to,x))//判断环
{
ff=1;
return;
}
f[e[i].to].s=min(f[e[i].to].s,f[x].s+1);
if(!v[e[i].to])
{
v[e[i].to]=1;
q.push(e[i].to);
}
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
char c[10];
scanf("%s",c+1);
int x,y;
if(c[2]>'9') x=c[2]-54;
else x=c[2]-47;
if(c[4]>'9') y=c[4]-54;
else y=c[4]-47;
add(x,y);
f[x].p=x;
f[y].p=y;
fa[y]++;
ap[x]=ap[y]=1;
}
for(int i=1;i<=36;i++)
{
if(fa[i]==0&&ap[i])
{
for(int j=1;j<=36;j++) f[j].s=0x3f3f3f3f;
memset(v,0,sizeof(v));
ff=0;
bfs(i);
if(ff==1) continue;//有环,跳过本树
cnt++;
cout<<cnt<<':';
for(int i=1;i<=36;i++) t[i].s=f[i].s,t[i].p=f[i].p;
sort(t+1,t+36+1,cmp);
if(t[1].p<=10&&ap[t[1].p]) cout<<t[1].p-1;
else if(t[1].p>10&&ap[t[1].p]) cout<<char(t[1].p+54);
for(int j=2;j<=36;j++)
{
if(!ap[t[j].p]||t[j].s==1061109567||t[j].s==0) continue;
if(t[j].s!=t[j-1].s) cout<<',';
if(t[j].p<=10) cout<<t[j].p-1;
else cout<<char(t[j].p+54);
}
cout<<endl;
}
}
if(cnt==0) cout<<"NO answer!";
else cout<<"total="<<cnt;
return 0;
}