L2-025 分而治之 并查集
样例
输入样例:
10 11
8 7
6 8
4 5
8 4
8 1
1 2
1 4
9 8
9 1
1 10
2 4
5
4 10 3 8 4
6 6 1 7 5 4 9
3 1 8 4
2 2 8
7 9 8 7 6 5 4 2
输出样例:
NO
YES
YES
NO
NO
分析:
先将所有边记录下来,再每次询问时,用并查集处理所有没被摧毁的边,记录连通块即fa[x]=x的数量与没被摧毁的城市数量比较
代码:
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>const int INF = 0x3f3f3f3f;
const int N = 1e4+10;int fa[N];
vector<int> v[N];void init(int n) { for ( int i = 1 ; i <= n ; i++ ) fa[i] = i; } //初始化
int find(int x) { return fa[x] == x ? x : fa[x] = find( fa[x] ); } //查找 路径压缩
void merge(int a, int b) { a = find(a), b = find(b), fa[b] = a; } //合并 int main(){int n, m; scanf("%d%d", &n, &m);while ( m-- ) {int x, y; scanf("%d%d",&x, &y);v[x].push_back(y);}scanf("%d", &m);while( m-- ){set<int> s; //用set存被摧毁的城市 方便查找 int k, num; scanf("%d", &k);num = k;while ( k-- ) {int x; scanf("%d",&x);s.insert(x);}init(n);for ( int i = 1 ; i <= n ; i++ ){for ( int j = 0 ; j < v[i].size() ; j++ ){if(s.count(i)==0 && s.count(v[i][j])==0) //路径两端都没被摧毁 merge(i, v[i][j]);}}int cnt = 0; for ( int i = 1 ; i <= n ; i++ ) if ( fa[i] == i && s.count(i) == 0) cnt++; if ( cnt >= n-num ) printf("YES\n");else printf("NO\n");}return 0;
}
L2-026 小字辈 递归
样例
输入样例:
9
2 6 5 5 -1 5 6 4 7
输出样例:
4
1 9
分析:
先计算出所有人辈分(本文利用递归),再找到所有最小辈分的人
代码:
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>const int INF = 0x3f3f3f3f;
const int N = 1e5+10;int fa[N],bf[N];int fun(int x){ //递归计算辈分 if ( bf[x] ) return bf[x]; //避免重复计算 if ( x == -1 ) return 0;return bf[x] = 1+fun(fa[x]);
}int main(){int n; scanf("%d", &n);for ( int i = 1 ; i <= n ; i ++ ){int x; scanf("%d",&x);fa[i] = x;}for ( int i = 1 ; i <= n ; i ++ ) //计算成员辈分 fun(i);int ans = 0;for ( int i = 1 ; i <= n ; i ++ ) //寻找最小辈分 ans = max(ans, bf[i]);printf("%d\n", ans);vector<int> v;for ( int i = 1 ; i <= n ; i ++ ) //存答案 if ( bf[i] == ans ) v.push_back(i);for ( int i = 0 ; i < v.size() ; i ++ )printf("%d%c", v[i] , i == v.size()-1 ? '\n' : ' ');return 0;
}
L2-027 名人堂与代金券 排序
样例
输入样例:
10 80 5
cy@zju.edu.cn 78
cy@pat-edu.com 87
1001@qq.com 65
uh-oh@163.com 96
test@126.com 39
anyone@qq.com 87
zoe@mit.edu 80
jack@ucla.edu 88
bob@cmu.edu 80
ken@163.com 70
输出样例:
360
1 uh-oh@163.com 96
2 jack@ucla.edu 88
3 anyone@qq.com 87
3 cy@pat-edu.com 87
5 bob@cmu.edu 80
5 zoe@mit.edu 80
分析:
水题,直接结构体存数据再排序就好,注意排名可以并列即可
代码:
因为用的数据结构不同,所以代码有所不同,区别在于重载处比较的写法
string存邮箱
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>const int INF = 0x3f3f3f3f;
const int N = 1e4+10;struct node{string name;int num;const bool operator<(const node &t) {if (num == t.num) return name < t.name;return num > t.num;}
}stu[N];int main(){int n, g, k;scanf("%d%d%d", &n, &g, &k);int sum = 0;for ( int i = 1 ; i <= n ; i ++ ){cin >> stu[i].name >> stu[i].num;if ( stu[i].num >= g) sum += 50;else if ( stu[i].num >= 60 ) sum += 20;}printf("%d\n",sum);sort(stu+1,stu+n+1);int cnt = 1;for ( int i = 1 ; i <= n ; i ++ ){if ( stu[i].num < stu[i-1].num ) cnt=i;if ( cnt > k ) break;cout << cnt << " " << stu[i].name << " " << stu[i].num << endl;}return 0;
}
char存邮箱
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>const int INF = 0x3f3f3f3f;
const int N = 1e4+10;struct node{char name[20];int num;const bool operator<(const node &t) {if (num == t.num) return strcmp(name,t.name)<0;return num > t.num;}
}stu[N];int main(){int n, g, k;scanf("%d%d%d", &n, &g, &k);int sum = 0;for ( int i = 1 ; i <= n ; i ++ ){scanf("%s %d", stu[i].name, &stu[i].num);if ( stu[i].num >= g) sum += 50;else if ( stu[i].num >= 60 ) sum += 20;}printf("%d\n",sum);sort(stu+1,stu+n+1);int cnt = 1;for ( int i = 1 ; i <= n ; i ++ ){if ( stu[i].num < stu[i-1].num ) cnt=i;if ( cnt > k ) break;printf("%d %s %d\n", cnt, stu[i].name, stu[i].num);}return 0;
}
L2-028 秀恩爱分得快 模拟
样例
输入样例 1:
10 4
4 -1 2 -3 4
4 2 -3 -5 -6
3 2 4 -5
3 -6 0 2
-3 2
输出样例 1:
-3 2
2 -5
2 -6
输入样例 2:
4 4
4 -1 2 -3 0
2 0 -3
2 2 -3
2 -1 2
-3 2
输出样例 2:
-3 2
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 3;
typedef long long ll;
int n, m, a, b, t, x, y;
string s; //字符串读入,用于判断"-0".用int无法判断-0的情况
vector<int> v[N]; //记录照片信息
double sum[N][N]; //亲密度总和
int sex[N]; // 1->男 -1->女
void O(int x) { //输出,因为输出"-0" 需要特判if (x == 0 && sex[0] == -1) cout << '-';cout << sex[abs(x)] * abs(x); //这样子输入普通i,也能输出正确的性别
}
int work(int i, int a) { //判断有无该情侣,有的话计算亲密度总和auto q = lower_bound(v[i].begin(), v[i].end(), a);int tmp = 0;if (*q == a) { //在照片中有a这个人x = sex[abs(a)];for (int j = 0; j < v[i].size(); j++) {y = sex[abs(v[i][j])];if (x * y < 0) { //只有异性才计算亲密度sum[abs(a)][abs(v[i][j])] += 1.0 / (v[i].size() * 1.0);sum[abs(v[i][j])][abs(a)] += 1.0 / (v[i].size() * 1.0);}}return 1;}return 0;
}
int main() {cin >> n >> m;for (int i = 1; i <= m; i++) {cin >> a;for (int j = 1; j <= a; j++) {cin >> s;t = stoi(s); // string 转 intv[i].push_back(t);sex[abs(t)] = s[0] == '-' ? -1 : 1; //判断男女}sort(v[i].begin(), v[i].end());} //坑点,性别信息可能不在照片里,在给出的情侣里cin >> s;a = stoi(s);sex[abs(a)] = s[0] == '-' ? -1 : 1;cin >> s;b = stoi(s);sex[abs(b)] = s[0] == '-' ? -1 : 1;for (int i = 1; i <= m; i++) {int tmp = 0;tmp += work(i, a);tmp += work(i, b);if (tmp == 2) { //去掉重复相加的sum[abs(a)][abs(b)] -= 1.0 / (v[i].size() * 1.0);sum[abs(b)][abs(a)] -= 1.0 / (v[i].size() * 1.0);}}double Max1 = 0, Max2 = 0;for (int i = 0; i < n; i++) Max1 = max(Max1, sum[abs(a)][i]);for (int i = 0; i < n; i++) Max2 = max(Max2, sum[abs(b)][i]);if (Max1 == Max2 && sum[abs(a)][abs(b)] == Max1)O(a), cout << " ", O(b), cout << endl;else {for (int i = 0; i < n; i++)if (sex[abs(a)] * sex[i] < 0 && sum[abs(a)][i] == Max1)O(a), cout << " ", O(i), cout << endl;for (int i = 0; i < n; i++)if (sex[abs(b)] * sex[i] < 0 && sum[abs(b)][i] == Max2)O(b), cout << " ", O(i), cout << endl;}
}
L2-029 特立独行的幸福 数学
样例
输入样例 1:
10 40
输出样例 1:
19 8
23 6
28 3
31 4
32 3
**注意:**样例中,10、13 也都是幸福数,但它们分别依附于其他数字(如 23、31 等等),所以不输出。其它数字虽然其实也依附于其它幸福数,但因为那些数字不在给定区间 [10, 40] 内,所以它们在给定区间内是特立独行的幸福数。
输入样例 2:
110 120
输出样例 2:
SAD
代码:
#include<bits/stdc++.h>
using namespace std;
int is_prime(int n){if(n<2) return 1;for(int i=2;i<=sqrt(n);i++)if(n%i==0) return 1;return 2;
}
int main(){int left,right,appear[100001]={0};cin>>left>>right;map<int,int> result; for(int i=left;i<=right;i++){int n=i,sum=0;vector<int> v;while(n!=1){sum=0;while(n){sum+=(n%10)*(n%10);n/=10; }n=sum;if(find(v.begin(),v.end(),sum)!=v.end()) break; //判断重复v.push_back(n);appear[n]=1;}if(n==1) result[i]=v.size(); }map<int,int>::iterator it;int flag=0;for(it=result.begin();it!=result.end();it++){if(!appear[it->first]){printf("%d %d\n",it->first,it->second*is_prime(it->first));flag=1;}}if(flag==0) printf("SAD");return 0;
}
L2-030 冰岛人
样例
输入样例:
15
chris smithm
adam smithm
bob adamsson
jack chrissson
bill chrissson
mike jacksson
steve billsson
tim mikesson
april mikesdottir
eric stevesson
tracy timsdottir
james ericsson
patrick jacksson
robin patricksson
will robinsson
6
tracy tim james eric
will robin tracy tim
april mike steve bill
bob adam eric steve
tracy tim tracy tim
x man april mikes
输出样例:
Yes
No
No
Whatever
Whatever
NA
代码
#include <bits/stdc++.h>
using namespace std;
bool judge(vector<int> &F, int s1, int s2){int n = F.size();vector<int> count(n, 0);vector<int> dist1(n, 0);vector<int> dist2(n, 0);int t ;count[s1]++;count[s2]++;while(F[s1] != -1){t = F[s1];count[t]++;dist1[t] = dist1[s1] + 1;if(t == s2) //直系祖宗...太乱了,直接false,不加这个,会有两个点过不去return false;s1 = t;}while(F[s2] != -1){t = F[s2];count[t]++;dist2[t] = dist2[s2] + 1;if(count[t] > 1){if(dist2[t]>=4 && dist1[t] >= 4)return true;elsereturn false;}s2 = t;}return true;
}
int main()
{int n;cin >> n;string f1, f2;vector<bool> sex(n);vector<vector<string> > record(n);map<string, int> M; //给每个人编号vector<int> F(n, -1); //父节点编号int cnt = 0;for(int i=0;i<n;i++){ //编号cin >> f1 >> f2;M.insert(make_pair(f1, cnt));int l = f2.size();if(f2[l-1] == 'm' || f2[l-1] == 'n')sex[cnt] = 1; //男elsesex[cnt] = 0;cnt++;record[i].push_back(f1);record[i].push_back(f2);}string par;for(int i=0;i<n;i++){ //找父节点f1 = record[i][0];f2 = record[i][1];int len = f2.size();if(f2[len-1] != 'r' && f2[len-1] != 'n') //老祖宗continue;if(sex[M[f1]] == true)par = f2.substr(0, len-4);elsepar = f2.substr(0, len-7);F[M[f1]] = M[par];}int m;cin >> m;string t1,t2;for(int i=0;i<m;i++){cin >> f1 >> f2 >> t1 >> t2;if(M.find(f1) == M.end() || M.find(t1) == M.end() ) {cout << "NA" << endl;continue;}if(sex[M[f1]] == sex[M[t1]]) {cout << "Whatever" << endl;continue;}if(judge(F, M[f1], M[t1])) {cout << "Yes" << endl;}elsecout << "No" << endl;}return 0;
}
L2-031 深入虎穴 dfs
样例
输入样例:
13
3 2 3 4
2 5 6
1 7
1 8
1 9
0
2 11 10
1 13
0
0
1 12
0
0
输出样例:
12
代码:
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>const int INF = 0x3f3f3f3f;
const int N = 1e5+10;int fa[N],dis[N];int dfs(int x, int id){if ( x == id ) return 0;if ( dis[x] != 0 ) return dis[x];return dis[x] = 1 + dfs(fa[x], id);
}int main(){int n; scanf("%d", &n);for ( int i = 1 ; i <= n ; i ++ ) fa[i] = i;for ( int i = 1 ; i <= n ; i ++ ){int k; scanf("%d", &k);while( k -- ){int x; scanf("%d", &x);fa[x] = i;}}int id;for ( int i = 1 ; i <= n ; i ++ ) if ( fa[i] == i ){id = i;break;}for ( int i = 1 ; i <= n ; i ++ ) dfs(i, id);int maxdis = -1, maxid = 0;for ( int i = 1 ; i <= n ; i ++ )if ( maxdis < dis[i])maxdis = dis[i], maxid = i;printf("%d\n", maxid);return 0;
}
L2-032 彩虹瓶 栈
样例
输入样例:
7 5 3
7 6 1 3 2 5 4
3 1 5 4 2 6 7
7 6 5 4 3 2 1
输出样例:
YES
NO
NO
代码:
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>const int INF = 0x3f3f3f3f;
const int N = 1e3+10;int fun(vector<int> v, int m){stack<int> s;int d = 1;for ( int i = 0 ; i < v.size() ; i ++ ){s.push(v[i]);while( s.size() && s.top() == d ){d ++;s.pop();}if ( s.size() > m ) return false;}if (s.empty() ) return true;else return false;
}int main(){int n, m ,k;scanf("%d%d%d", &n, &m, &k);while ( k -- ){vector<int> v;int d = 1;for ( int i = 0 ; i < n ; i ++ ){int x; scanf("%d", &x);v.push_back(x);}if ( fun(v, m) ) printf("YES\n");else printf("NO\n"); } return 0;
}
L2-033 简单计算器 栈
样例
输入样例 1:
5
40 5 8 3 2
/ * - +
输出样例 1:
2
输入样例 2:
5
2 5 8 4 4
* / - +
输出样例 2:
ERROR: 5/0
代码:
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>const int INF = 0x3f3f3f3f;
const int N = 1e3+10;void fun(vector<int> vi, vector<char> vc){stack<int> si;stack<char> sc; for ( int i = 0 ; i < vi.size() ; i ++ ) si.push(vi[i]);for ( int i = 0 ; i < vc.size() ; i ++ ) sc.push(vc[i]);int ans=1;while ( sc.size() ) {int n1, n2;n1 = si.top(); si.pop();n2 = si.top(); si.pop();
// cout<<n1<<" "<<n2<<" "<<sc.top()<<endl;if ( sc.top() == '+' ) ans = n2 + n1;if ( sc.top() == '-' ) ans = n2 - n1;if ( sc.top() == '*' ) ans = n2 * n1;if ( sc.top() == '/' ) {if ( n1 == 0){printf("ERROR: %d/0\n", n2);return ;}ans = n2 / n1;}sc.pop();si.push(ans);}printf("%d\n", si.top());
}int main(){int n; scanf("%d",&n);vector<int> vi;vector<char> vc;for ( int i = 1 ; i <= n ; i ++ ){int x; scanf("%d", &x);vi.push_back(x);}for ( int i = 1 ; i < n ; i ++ ){char c[5]; scanf("%s", c);vc.push_back(c[0]);}fun(vi, vc);return 0;
}
L2-034 口罩发放 模拟
样例
输入样例:
4 2
5 3
A 123456789012345670 1 13:58
B 123456789012345671 0 13:58
C 12345678901234567 0 13:22
D 123456789012345672 0 03:24
C 123456789012345673 0 13:59
4 3
A 123456789012345670 1 13:58
E 123456789012345674 0 13:59
C 123456789012345673 0 13:59
F F 0 14:00
1 3
E 123456789012345674 1 13:58
1 1
A 123456789012345670 0 14:11
输出样例:
D 123456789012345672
A 123456789012345670
B 123456789012345671
E 123456789012345674
C 123456789012345673
A 123456789012345670
A 123456789012345670
E 123456789012345674
分析
坑:
condition==1 的记录按输入顺序输出
时间一样记录 按输入顺序输出
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5+5;struct node{string name,ID;int condition,hh,mm,num;
}people[maxn];bool cmp(node a,node b){if(a.hh == b.hh) {if(a.mm == b.mm) return a.num<b.num;return a.mm<b.mm;}return a.hh<b.hh;
}//# define pair<string,string> pss;
vector < pair < string,string > > ans1,ans2;
map<string,int> mp1,mp2;bool checkID(string id){if(id.size()!=18) return false;for(int i = 0 ; i < id.size(); i++)if(id[i]<'0' || id[i]>'9') return false;return true;
}int main(){int d,p; cin>>d>>p; //D 天的数据 至少需要间隔 P 天for(int i = 0 ; i < d ; i ++ ){int t,s; cin>>t>>s; // T条申请,总共有 S个口罩发放名额for(int j = 0 ; j < t ; j ++){ // 输入 姓名 身份证号 身体情况 提交时间cin>>people[j].name>>people[j].ID;scanf("%d %d:%d",&people[j].condition,&people[j].hh,&people[j].mm);people[j].num=j;if(people[j].condition==1 && mp2.find(people[j].ID) == mp2.end() && checkID(people[j].ID)){ // 记录有合法记录的、身体状况为 1 的申请人的姓名及身份证号ans2.push_back(make_pair(people[j].name, people[j].ID));mp2[people[j].ID] = 1;}}sort(people,people+t,cmp);for(int j = 0 ; j < t ; j ++){if(!checkID(people[j].ID)) continue;//身份证号 必须是 18 位的数字if(s>0){if(mp1.find(people[j].ID) == mp1.end() || mp1[people[j].ID]+p < i){ // 该id还未申请过 或者 过了i+P+1天 mp1[people[j].ID] = i; // 记录这次次领取时间cout<< people[j].name<< ' '<< people[j].ID << endl;s--;}}}}for(int i = 0 ; i < ans2.size() ; i ++) cout << ans2[i].first << " " << ans2[i].second << endl;
}
L2-035 完全二叉树的层序遍历 树
样例
输入样例:
8
91 71 2 34 10 15 55 18
输出样例:
18 34 55 71 2 10 15 91
分析:
完全二叉树采用顺序存储方式,如果有左孩子,则编号为2i,如果有右孩子,编号为2i+1,然后按照后序遍历的方式(左右根),进行输入,最后顺序输出即可
代码:
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>const int INF = 0x3f3f3f3f;
const int N = 1e3+10;int n, tree[31];void create(int i) {if (i > n) return;create(2 * i);create(2 * i + 1);scanf("%d", &tree[i]);
}int main() {cin >> n;create(1);for ( int i = 1; i <= n; i ++) printf ("%d%c", tree[i], i==n ? '\n' : ' ');return 0;
}
L2-036 网红点打卡攻略 模拟
样例
输入样例:
6 13
0 5 2
6 2 2
6 0 1
3 4 2
1 5 2
2 5 1
3 1 1
4 1 2
1 6 1
6 3 2
1 2 1
4 5 3
2 0 2
7
6 5 1 4 3 6 2
6 5 2 1 6 3 4
8 6 2 1 6 3 4 5 2
3 2 1 5
6 6 1 3 4 5 2
7 6 2 1 3 4 5 2
6 5 2 1 4 3 6
输出样例:
3
5 11
样例说明:
第 2、3、4、6 条都不满足攻略的基本要求,即不能做到从家里出发,在每个网红点打卡仅一次,且能回到家里。所以满足条件的攻略有 3 条。
第 1 条攻略的总路费是:(0->5) 2 + (5->1) 2 + (1->4) 2 + (4->3) 2 + (3->6) 2 + (6->2) 2 + (2->0) 2 = 14;
第 5 条攻略的总路费同理可算得:1 + 1 + 1 + 2 + 3 + 1 + 2 = 11,是一条更省钱的攻略;
第 7 条攻略的总路费同理可算得:2 + 1 + 1 + 2 + 2 + 2 + 1 = 11,与第 5 条花费相同,但序号较大,所以不输出。
代码:
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>const int INF = 0x3f3f3f3f;
const int N = 1e3+10;int main(){int n, m;scanf("%d%d", &n, &m);int mp[n+5][n+5];for ( int i = 0 ; i <= n ; i ++ )for ( int j = 0 ; j <= n ; j ++ )mp[i][j] = mp[j][i] = 0;for ( int i = 1 ; i <= m ; i ++ ){int x, y, w; scanf("%d%d%d", &x, &y, &w);mp[x][y] = mp[y][x] = w;}vector<PII> ans;int q, minw=INF; scanf("%d", &q);for ( int i = 1 ; i <= q ; i ++ ){int k; scanf("%d", &k);vector<int> v;set<int> s;v.push_back(0);for (int j = 0 ; j < k ; j ++ ){int x; scanf("%d", &x);v.push_back(x);s.insert(x);}v.push_back(0);int w = 0;if(k != n || s.size() != n) continue;bool flag = true;for (int j = 0 ; j < v.size()-1 ; j ++ ){if (mp[v[j]][v[j+1]]!=0) w += mp[v[j]][v[j+1]];else {flag = false;break;}}if (!flag) continue;minw = min(minw, w);ans.push_back({i, w});}printf("%d\n", ans.size());for ( int i = 0 ; i < ans.size() ; i ++ )if ( ans[i].second == minw ){printf("%d %d\n", ans[i].first, ans[i].second);break;}return 0;
}
L2-037 包装机 栈和队列
图1 自动包装机的结构
图 2 顺序按下按钮 3、2、3、0、1、2、0 后包装机的状态
样例
输入样例:
3 4 4
GPLT
PATA
OMSA
3 2 3 0 1 2 0 2 2 0 -1
输出样例:
MATA
分析:
队列模拟传送带,栈模拟筐
代码:
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>const int INF = 0x3f3f3f3f;
const int N = 1e3+10;int main(){int n, m, s; scanf("%d%d%d", &n, &m, &s);queue<int> q[n+5];stack<int> sta;for ( int i = 1 ; i <= n ; i ++ ){ //第i号轨道 char str[m+5]; scanf("%s",str);for ( int j = 0 ; j < m ; j ++ ) //第j个物品 q[i].push(str[j]-'A');}int x;while ( scanf("%d", &x) && x != -1){if ( x > 0 && q[x].size() ){int t = q[x].front();q[x].pop();if(sta.size() == s) {printf("%c", sta.top()+'A');sta.pop();}sta.push(t);}if ( x == 0 && sta.size() ){printf("%c", sta.top()+'A');sta.pop();}}return 0;
}
L2-038 病毒溯源 dfs
样例
输入样例:
10
3 6 4 8
0
0
0
2 5 9
0
1 7
1 2
0
2 3 1
输出样例:
4
0 4 9 1
代码:
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>const int INF = 0x3f3f3f3f;
const int N = 1e4+10;int vis[N], maxk;
vector<int> v[N], ans, t;void dfs(int id, int k){if ( k > maxk ){maxk = k;ans = t;}for ( int i = 0 ; i < v[id].size() ; i ++ ){t.push_back(v[id][i]);dfs(v[id][i], k+1);t.pop_back();}return ;
}int main(){int n;scanf("%d", &n);for ( int i = 0 ; i < n ; i ++ ){int k; scanf("%d", &k);while ( k -- ){int x; scanf("%d", &x);vis[x] = 1;v[i].push_back(x);}sort(v[i].begin(), v[i].end());}int id; //病毒源头for ( int i = 0 ; i < n ; i ++ ){if( vis[i] == 0 ) {id = i;break; }}dfs(id, 1); printf("%d\n%d", maxk, id);for (int i = 0 ; i < ans.size() ; i ++ )printf(" %d",ans[i]);return 0;
}
L2-039 清点代码库 排序
样例
输入样例:
7 3
35 28 74
-1 -1 22
28 74 35
-1 -1 22
11 66 0
35 28 74
35 28 74
输出样例:
4
3 35 28 74
2 -1 -1 22
1 11 66 0
1 28 74 35
代码:
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>const int INF = 0x3f3f3f3f;
const int N = 1e4+10;struct cmp{ //自定义set排序bool operator() (const pair<int,vector<int> >&a, const pair<int,vector<int> >&b) const{if(a.first!=b.first) return a.first>b.first;else return a.second<b.second;}
};int main(){int n, m; scanf("%d%d", &n, &m);set<vector<int> > st; //存模块map<vector<int>, int> mp; //存每个模块的个数set<pair<int,vector<int> >,cmp > St;//排序for ( int i = 0 ; i < n ; i ++ ){vector<int> v;for ( int j = 0 ; j < m ; j ++ ){int x; scanf("%d", &x);v.push_back(x);}mp[v] ++;st.insert(v);}printf("%d\n", st.size());//把所有模块存入ST排序 set<vector<int> >::iterator it;for(it = st.begin() ; it != st.end() ; it ++)St.insert({mp[*it],*it});//输出ST set<pair<int,vector<int> > >::iterator ite;for(ite = St.begin() ; ite != St.end() ; ite ++){cout << (*ite).first;for(int i = 0; i < (*ite).second.size() ; i++)cout<<' '<<(*ite).second[i];cout<<endl;}return 0;
}
L2-040 哲哲打游戏 模拟
样例
输入样例:
10 11
3 2 3 4
1 6
3 4 7 5
1 3
1 9
2 3 5
3 1 8 5
1 9
2 8 10
0
1 1
0 3
0 1
1 2
0 2
0 2
2 2
0 3
0 1
1 1
0 2
输出样例:
1
3
9
10
样例解释:
简单给出样例中经过的剧情点顺序:
1 -> 4 -> 3 -> 7 -> 8 -> 3 -> 5 -> 9 -> 10。
档位 1 开始存的是 1 号剧情点;档位 2 存的是 3 号剧情点;档位 1 后来又存了 9 号剧情点。
代码:
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>const int INF = 0x3f3f3f3f;
const int N = 1e3+10;vector<int> e[100010];
int que[110];int main(){int n, m; scanf("%d%d", &n, &m);for (int i = 1 ; i <= n ; i ++) {int t; scanf("%d", &t);while (t--){int x; scanf("%d", &x);e[i].push_back(x);}}int now = 1;while (m--) {int x, y; scanf("%d%d", &x, &y);if (x == 0)now = e[now][y - 1];else if (x == 1) {que[y] = now;printf("%d\n", now);}else if (x == 2)now = que[y];}printf("%d\n", now);return 0;
}
L2-041 插松枝 栈和队列
样例
输入样例:
8 3 4
20 25 15 18 20 18 8 5
输出样例:
20 15
20 18 18 8
25 5
代码
#include<bits/stdc++.h>
using namespace std;int main()
{queue<int> a;int n,m,k;cin>>n>>m>>k;for(int i=0;i<n;i++) {int x;cin>>x;a.push(x);} vector<vector<int>> ans;vector<int> st;stack<int> hz;int d;while(hz.size() || a.size()){if(st.size()!=0) d=st.back();else d=1e9;if(hz.size() && hz.top()<=d) //小盒子最上面符合条件,插入松针 {st.push_back(hz.top());hz.pop();if((int)st.size()==k) {ans.push_back(st);st.clear();}} else if(a.size() && a.front()<=d) //推送器最上面符合条件,插入松针 {st.push_back(a.front());a.pop();if((int)st.size()==k) {ans.push_back(st);st.clear();}}else if(a.size() && (int)hz.size()<m) //不能直接插入松针,推送器放入小盒子{hz.push(a.front());a.pop();} else //小盒子满了,推送器也不能插入,开启一个新的松针{ans.push_back(st);st.clear();} }if(st.size()) {ans.push_back(st);st.clear();} for(auto &p:ans){cout<<p[0];for(int i=1;i<(int)p.size();i++)cout<<" "<<p[i];cout<<endl;}return 0;
}
L2-042 老板的作息表 排序
样例
输入样例:
8
13:00:00 - 18:00:00
00:00:00 - 01:00:05
08:00:00 - 09:00:00
07:10:59 - 08:00:00
01:00:05 - 04:30:00
06:30:00 - 07:10:58
05:30:00 - 06:30:00
18:00:00 - 19:00:00
输出样例:
04:30:00 - 05:30:00
07:10:58 - 07:10:59
09:00:00 - 13:00:00
19:00:00 - 23:59:59
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
struct node{int sh,sm,ss,stime;int eh,em,es,etime;
}times[maxn];bool cmp(node a,node b){if(a.sh == b.sh){if(a.sm == b.sm) return a.ss < b.ss;return a.sm < b.sm;}return a.sh < b.sh;
}int main(){int n;cin>>n;//时间段的个数for(int i = 0 ; i < n ; i ++){scanf("%d:%d:%d - %d:%d:%d",×[i].sh,×[i].sm,×[i].ss,×[i].eh,×[i].em,×[i].es);times[i].stime=times[i].sh*3600+times[i].sm*60+times[i].ss;times[i].etime=times[i].eh*3600+times[i].em*60+times[i].es;}sort(times,times+n,cmp);if(times[0].stime!=0) printf("00:00:00 - %02d:%02d:%02d\n",times[0].sh,times[0].sm,times[0].ss);for(int i = 0 ; i < n-1 ; i ++)if(times[i].etime != times[i+1].stime)printf("%02d:%02d:%02d - %02d:%02d:%02d\n",times[i].eh,times[i].em,times[i].es,times[i+1].sh,times[i+1].sm,times[i+1].ss);if(times[n-1].etime != (23*3600+59*60+59) ) printf("%02d:%02d:%02d - 23:59:59\n",times[n-1].eh,times[n-1].em,times[n-1].es);}
L2-043 龙龙送外卖 dfs
样例
输入样例:
7 4
-1 1 1 1 2 2 3
5
6
2
4
输出样例:
2
4
4
6
代码
#include<bits/stdc++.h>
using namespace std;const int maxn = 1e5+5;int parent[maxn]; //双亲结点编号
int dis[maxn]; //该点到根结点的距离
int vis[maxn]; // 是否访问过该点
int max_deep=0,ans=0;int dfs(int x){if(parent[x] == -1 || vis[x] == 1)return dis[x];vis[x] = 1;ans++;return dis[x] = dfs(parent[x]) + 1;
}int main(){memset(vis,0,sizeof(vis));int n,m; cin>>n>>m;//树上节点的个数,以及新增的送餐地址的个数for(int i = 1 ; i <= n ; i ++) cin>>parent[i];while(m--){int tmp; cin>>tmp; // 新增的送餐地点的编号int deep = dfs(tmp);max_deep = max(deep,max_deep);cout<<ans*2-max_deep<<endl;}
}
L2-044 大众情人 Floyd
样例
输入样例:
6
F 1 4:1
F 2 1:3 4:10
F 2 4:2 2:2
M 2 5:1 3:2
M 2 2:2 6:2
M 2 3:1 2:5
输出样例:
2 3
4
代码
#include<bits/stdc++.h>
using namespace std;const int INF = 0x3f3f3f3f;
const int maxn = 510;int g[maxn][maxn],sex[maxn],d[maxn];int main(){int n; cin>>n; // 总人数for(int i = 1 ; i <= n ; i ++) // 初始化for(int j = 1 ; j <= n ; j ++)if(i==j) g[i][j]=0;else g[i][j] = INF;for(int i = 1 ; i <= n ; i ++){ // 输出char op;int k; cin>>op>>k;if(op=='F') sex[i] = 0; //女生else sex[i] = 1; // 男生for(int j = 1 ; j <= k ; j ++){int a,b;scanf("%d:%d",&a,&b);g[i][a] = b;}}for(int k = 1 ; k <= n ; k ++) // Floyd 求每个人直接的最短距离for(int i = 1 ; i <= n ; i ++)for(int j = 1 ; j <= n ; j ++)g[i][j] = min(g[i][k]+g[k][j], g[i][j]);for(int i = 1 ; i <= n ; i ++) // 每个人到异性的最大距离for(int j = 1 ; j <= n ; j ++)if(sex[i] != sex[j]) d[i] = max(d[i], g[j][i]);int d0=INF,d1=INF;//d0表示女对男的距离 d2表示男对女的距离 for(int i = 1 ; i <= n ; i ++) // 求大众情人与异性的距离if(sex[i] == 0) d0 = min(d0, d[i]);else d1 = min(d1,d[i]);vector<int> a,b;for(int i = 1 ; i <= n ; i ++){//求大众情人编号 if(sex[i] == 0 && d[i] == d0) a.push_back(i); // 女大众情人if(sex[i] == 1 && d[i] == d1) b.push_back(i); // 男大众情人}cout<<a[0]; // 输出for(int i = 1 ; i < a.size() ; i ++){cout<<" "<<a[i];}cout<<endl<<b[0];for(int i = 1 ; i < b.size() ; i ++){cout<<" "<<b[i];}
}
L2-045 堆宝塔 模拟
样例
输入样例:
11
10 8 9 5 12 11 4 3 1 9 15
输出样例:
4 5
样例解释:
宝宝堆成的宝塔顺次为:
- 10、8、5
- 12、11、4、3、1
- 9
- 15、9
代码
#include<bits/stdc++.h>
using namespace std;vector<int> a,b;
vector<vector<int>> res;int main(){int n;cin>>n;// 彩虹圈的个数while(n--){int x;cin>>x; // 彩虹圈的直径if(a.empty()) //如果 A 为空,先放一个a.push_back(x);else if(x<a.back()) //如果比 A 最上面的小,就直接放上去a.push_back(x);else if(b.empty()||x>b.back())//如果 B 柱是空的、或者 C 大,就在 B 柱上放好;b.push_back(x);else{res.push_back(a); a.clear(); // A 记作一件成品while(!b.empty() && b.back()>x){ // 把 B 柱上所有比 C 大的彩虹圈逐一取下放到 A 柱上a.push_back(b.back());b.pop_back();}a.push_back(x); // 最后把 C 也放到 A 柱上}}if(!a.empty()) res.push_back(a);if(!b.empty()) res.push_back(b);int maxx=0;for(int i = 0 ; i < res.size() ; i++)maxx = max(maxx, (int)res[i].size()); // max的两个参数要相同规模cout<<(int)res.size()<<" "<<maxx;
}
L2-046 天梯赛的赛场安排 优先队列
样例
输入样例:
10 30
zju 30
hdu 93
pku 39
hbu 42
sjtu 21
abdu 10
xjtu 36
nnu 15
hnu 168
hsnu 20
输出样例:
zju 1
hdu 4
pku 2
hbu 2
sjtu 1
abdu 1
xjtu 2
nnu 1
hnu 6
hsnu 1
16
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5005;
typedef pair<int,string> PII;string name[maxn];
int ren[maxn],cnt[100*maxn],sum[maxn];
map<string,int> mp;
priority_queue<PII> q;int main(){int n,c; cin>>n>>c; // 参赛学校数量和每个赛场的规定容量for(int i = 1 ; i <= n ; i ++){cin>>name[i]>>ren[i];//输入学校名和对应人数mp[name[i]]=i;//记录该学校对应的id位置q.push({ren[i],name[i]});}int m=0;//m是当前开设了多少个赛场while(q.size()){int k = q.top().first;string name = q.top().second;q.pop();sum[mp[name]]++;//新开一个赛场if(k >= c){ //第一种情况cnt[++m]=0; k-=c; //因为k>=c,那么新开设的肯定是直接满人if(k) q.push({k,name});//如果还有剩余,再塞进去排continue;}int flag=0;//记录是否找到满足条件的赛场for(int i = 1 ; i <= m ; i ++) if(cnt[i]>=k) {//第二种情况flag = 1;cnt[i] -= k;break;}if(!flag) cnt[++m]=c-k; 第三种情况 找不到满足的,新开设一个}for(int i=1;i<=n;i++) cout<<name[i]<<" "<<sum[mp[name[i]]]<<'\n';printf("%d\n",m);return 0;
}
L2-047 锦标赛 模拟
样例
输入样例1:
3
4 5 8 5
7 6
8
9
输出样例1:
7 4 8 5 9 8 6 5
输入样例2:
2
5 8
3
9
输出样例2:
No Solution
提示:
本题返回结果若为格式错误均可视为答案错误。
代码
#include <iostream>
using namespace std;
int k, w, lost[19][1 << 18], win[19][1 << 18], ans[1 << 18];
int main() {cin >> k;for (int i = 1; i <= k; i++) {for (int j = 0; j < (1 << (k - i)); j++) {cin >> lost[i][j];if (i == 1) {ans[j << 1] = lost[i][j];win[i][j] = j << 1 | 1;} else {if (lost[i][j] < lost[i - 1][j << 1] && lost[i][j] < lost[i - 1][j << 1 | 1]) {cout << "No Solution";return 0;} else if (lost[i][j] >= lost[i - 1][j << 1]) {ans[win[i - 1][j << 1]] = lost[i][j];win[i][j] = win[i - 1][j << 1 | 1];} else {ans[win[i - 1][j << 1 | 1]] = lost[i][j];win[i][j] = win[i - 1][j << 1];}lost[i][j] = max(lost[i][j], max(lost[i - 1][j << 1], lost[i - 1][j << 1 | 1])); }}}cin >> w;if(lost[k][0] > w) {cout << "No Solution";return 0;}ans[win[k][0]] = w;for (int i = 0; i < 1 << k; i++) {if (i) cout << ' ';cout << ans[i] ;}return 0;
}
L2-048 寻宝图 bfs/dfs
样例
输入样例:
10 11
01000000151
11000000111
00110000811
00110100010
00000000000
00000111000
00114111000
00110010000
00019000010
00120000001
输出样例:
7 2
代码
#include<bits/stdc++.h>
using namespace std;const int maxn = 1e5+5;int n,m;
bool flag;
string mp[maxn];//如果用二维数组会内存超限
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};void dfs(int x, int y){if(x<0 || x>=n || y<0 || y>=m || mp[x][y]=='0') return; // 不能出岛if(mp[x][y]>'1') flag=1; //有宝藏mp[x][y]='0'; // 标记该点已搜索for(int i = 0 ; i < 4 ; i ++) // 搜索相邻点dfs(x+dx[i],y+dy[i]);
}void bfs(int a, int b){queue< pair<int,int> > que;que.push({a,b});while(que.size()){int x = que.front().first,y=que.front().second; que.pop();if(x<0 || x>=n || y<0 || y>=m || mp[x][y]=='0') continue; // 不能出岛if(mp[x][y]>'1') flag=1; //有宝藏mp[x][y]='0'; // 标记该点已搜索for(int i = 0 ; i < 4 ; i ++)que.push({x+dx[i], y+dy[i]});}
}void printmp(){cout<<endl;for(int i = 0 ; i < n ; i ++) cout<<mp[i]<<endl;cout<<endl;
}int main(){cin>>n>>m; // 地图的尺寸for(int i = 0 ; i < n ; i ++) cin>>mp[i];//每一行存储到字符串中int cns=0,cnt=0;for(int i = 0 ; i < n ; i ++) for(int j = 0 ; j < m ; j++)if(mp[i][j] > '0'){ // 从一个没有被搜索过的岛屿块出发cns++;//岛屿数量加1flag=0;//宝藏标记置为0bfs(i,j);//标记与之连通的岛屿块if(flag) cnt++;//有宝藏// printmp();}cout<<cns<<" "<<cnt<<endl;
}