题解 P5833 【[USACO19DEC]Livestock Lineup牲畜阵容】
zimindaada · · 题解
题解 P5833 【[USACO19DEC]Livestock Lineup牲畜阵容】
题意:已知
这一道题我用的很奇怪的方法,有点想复杂了。其实可以用全排列直接算一遍的(我同学说是这么做的)
我用的是一个双向链表
然后从字典序小的往后遍历,如果度为
另外,在往下搜的过程中,必须要打
如果还有看不懂的,看代码吧,注释很详细。
//Code by zimindaada in 20191220
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
int n;
char beat[] = "Beatrise", beli[] = "Belinde", bell[] = "Bella", bess[] = "Bessie", \
bets[] = "Betsy", blue[] = "Blue", butt[] = "Buttercup";//因为cmp不能直接用"Bessie"来做参数所以搞了这个愚蠢的玩意儿……
inline bool cmp(char a[], char b[]){//我不太会用char数组,所以打了一个奇怪的cmp来代替==
int l = strlen(b);
for(int i = 0; i < l; ++i){
if(a[i] != b[i]) return 0;
}
return 1;
}
inline int convert(char t[]){//为了方便,把名字按顺序转换成数字
if(cmp(t, beat)) return 1;
else if(cmp(t, beli)) return 2;
else if(cmp(t, bell)) return 3;
else if(cmp(t, bess)) return 4;
else if(cmp(t, bets)) return 5;
else if(cmp(t, blue)) return 6;
else if(cmp(t, butt)) return 7;
else return 8;
}
int de[10];//每个牛的度(或者说是每个牛已经和几个牛确定了关系)
int lb[10][2];//双向链表
bool vis[10];//vis标记
inline string back(int t){//从数字转换回字符串的函数
if(t == 1) return "Beatrise";
else if(t == 2) return "Belinde";
else if(t == 3) return "Bella";
else if(t == 4) return "Bessie";
else if(t == 5) return "Betsy";
else if(t == 6) return "Blue";
else if(t == 7) return "Buttercup";
else return "Sue";
}
//核心函数//
void dfs(int fa, int x){//fa代表上一个,x代表目前的
//首先因为前面已经被选了,所以它必须被选
cout << back(x) << endl;
for(int i = 1; i <= de[x]; ++i){
if(lb[x][i] != fa && !vis[lb[x][i]]){//确保搜到的不是上一个
vis[lb[x][i]] = 1;
dfs(x, lb[x][i]);
}
}
}
int main(){
scanf("%d",&n);
char s1[15], s2[15];//输入用变量
for(int i = 1; i <= n; ++i){
scanf("%s must be milked beside %s",s1, s2);//输入
int x1 = convert(s1), x2 = convert(s2);
lb[x1][++de[x1]] = x2; lb[x2][++de[x2]] = x1;//链表存
}
//核心代码//
for(int i = 1; i <= 8; ++i){//遍历一遍八头牛
//由字典序定义,前面越小字典序小,所以尽可能让更前面的更小
if(vis[i]) continue;//如果遍历/dfs过了一遍,就跳过
if(de[i] == 0){//如果没有关系
//因为遍历到它,说明当前最好的方案就是选他,
cout << back(i) << endl;//就可以直接放。
vis[i] = 1;//记得打标记
}else if(de[i] == 1){//如果有1个关系
vis[i] = 1;
//同上,但是因为它是一个链表的头,
dfs(-1,i);//所以要用dfs遍历一遍链表(用for或while也行)
}
}
return 0;
}
注:该代码有防抄措施,在题解非核心代码上的做了修改!