hihocoder-[Offer收割]编程练习赛25
题目1 : 皇室成员的名字
描述
小Ho正在学习世界历史。他发现历史上很多西方国家的皇室成员的名字都是由英文名字加罗马数字组成的,例如George IV(乔治四世)、William IV(威廉四世)、Elizabeth II(伊丽莎白二世)等。
为了更好的梳理历史脉络,小Ho决定写个程序把历史书上出现过的皇室名字排序:首先按英文名字的字典序排序,如果英文名字相同,再按罗马数字从小到大的顺序排序。
罗马数字表示可以参考 https://en.wikipedia.org/wiki/Roman_numerals 中的"standard forms"。
输入
第一行包含一个整数N,表示名字的总数。
以下N行每行包含一个名字。英文名字与罗马数字之间由一个空格隔开。其中英文名字首字母是大写字母,其余字母是小写字母。
对于100%的数据,1 ≤ N ≤ 100000, 罗马数字 < 4000
输出
输出N行,每行一个名字。
-
样例输入
-
5 Elizabeth II Elizabeth C William IV Hiho MMXVII Hiho MMXVII
样例输出
-
Elizabeth II Elizabeth C Hiho MMXVII Hiho MMXVII William IV
#include <cstdio>
#include <cstdlib>
#include <unordered_map>
#include <string>
#include <iostream>
using namespace std;
const int MAXN = 100000;
struct Node{
string n1, n2;
int num;
}nd[MAXN];
unordered_map<char, int> mp{{'I', 1}, {'V', 5}, \
{'X', 10}, {'L', 50}, {'C', 100}, {'D', 500}, {'M', 1000}};
int cmp(const void *a, const void *b){
Node *aa = (Node *)a;
Node *bb = (Node *)b;
if(aa->n1 == bb->n1){
return aa->num - bb->num;
}else if(aa->n1 > bb->n1){
return 1;
}else{
return -1;
}
}
int Compute(string s){
int res = 0;
for(int i=0; i<s.length(); ++i){
if(i==0 || mp[s[i]] <= mp[s[i-1]] ){
res += mp[s[i]];
}else{
res += mp[s[i]] - 2*mp[s[i-1]];
}
}
return res;
}
int main(){
int n;
while(cin >> n){
for(int i=0; i<n; ++i){
cin >> nd[i].n1 >> nd[i].n2;
nd[i].num = Compute(nd[i].n2);
}
qsort(nd, n, sizeof(nd[0]), cmp);
for(int i=0; i<n; ++i){
cout << nd[i].n1 << " " << nd[i].n2 << endl;
}
}
return 0;
}
题目2 : 偶树的切分
描述
如果一棵树节点数目是偶数,那么就称这棵树是偶树。给定一棵N个节点的偶树(编号1~N),小Hi想知道他最多可以同时切断多少条边,使得剩下的森林中每一个联通分量都是一棵偶树。
例如如下的偶树:
1 / | | \ 2 3 4 5 | 6
可以切断1-2之间边使得剩下的每个联通分量都是偶树。
输入
第一行包含一个偶数N。
以下N-1行每行包含两个整数a和b,表示a和b之间有一条边。
对于30%的数据,1 ≤ N ≤ 20
对于100%的数据, 1 ≤ N ≤ 100000
输出
输出最多可以切断的边数。
-
样例输入
-
6 1 2 3 1 4 1 1 5 6 2
样例输出
-
1
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <iostream>
using namespace std;
const int MAXN = 100000 + 100;
int n, u, v, ans;
vector<int> vt[MAXN];
int dfs(const int cur, const int pre){
if(vt[cur].size() == 1 && vt[cur][0] == pre){
return 1;
}
int cnt = 1;
for(int i=0; i<vt[cur].size(); ++i){
if(vt[cur][i] == pre){
continue;
}
cnt += dfs(vt[cur][i], cur);
}
if(cnt % 2 == 0){
++ans;
}
return cnt;
}
int main(){
while(scanf("%d", &n) != EOF){
for(int i=0; i<=n; ++i){
vt[i].clear();
}
for(int i=1; i<n; ++i){
scanf("%d %d", &u, &v);
vt[u].push_back(v);
vt[v].push_back(u);
}
if(n%2 == 1){
printf("0\n");
continue;
}
ans = 0;
dfs(1, 0);
printf("%d\n", (ans-1) );
}
return 0;
}