1003Emergency
最短路径问题——Dijkstra算法
选出最近的点,把该点加入集合
计算从该点出发到其他所有点的距离(排除集合中的点)
更新距离,救援队数量和路径数量,⚠️注意dis[now] + mmap[now][j] == dis[j]
的情况
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f
int n, m, s, e;
int team[1000];
int mmap[1000][1000];
int dis[1000], tol[1000], pathnum[1000], set[1000] = {0};
//dis表示原点到某点的距离,set表示某点是否加入集合,tol表示到某点的救援队数量,pathnum表示到某点的路径数量
void dijstra(){
for(int i=0; i<n; i++){
dis[i] = inf; //初始所有距离为无穷大
}
dis[s] = 0; //原点距离为0
tol[s] = team[s]; //原点的救援队数量为输入的数team[s]
pathnum[s] = 1; //初始路径为1
for(int i=0; i<n; i++){ //遍历所有点,加入集合
int mmin = inf;
int now; //now表示当前点,也就是最近的点
for(int j=0; j<n; j++){
if(dis[j] < mmin && set[j] == 0) {
mmin = dis[j];
now = j;
}
}
set[now] = 1; //把最短的点加入集合中
for(int j=0; j<n; j++){
if(set[j] == 0){
if(dis[now] + mmap[now][j] < dis[j]){ //更新距离,救援队数量,路径数量
dis[j] = dis[now] + mmap[now][j];
tol[j] = tol[now] + team[j];
pathnum[j] = pathnum[now];
}
else if(dis[now] + mmap[now][j] == dis[j]){
pathnum[j] += pathnum[now];
if(tol[j] < tol[now] + team[j])
tol[j] = tol[now] + team[j];
}
}
}
}
}
int main(){
cin >> n >> m >> s >> e;
for(int i=0; i<n; i++)
cin >> team[i];
memset(mmap,inf,sizeof(mmap)); //把map置为无穷大,表示各点之间断路
for(int i=0; i<m; i++){
int a, b;
cin >> a >> b;
cin >> mmap[a][b];
mmap[b][a] = mmap[a][b];
}
dijstra();
cout << pathnum[e] << " " << tol[e] << endl;
}
1004Counting Leaves
dfs算法,是叶子结点结束,非叶子结点继续dfs
#include<bits/stdc++.h>
using namespace std;
int n, m;
int maxlevel = 0;
vector<int> node[1000];
int level[1000] = {0};
void dfs(int a, int l){
if(node[a].size() == 0){ //若该节点为叶子节点,则该层+1,结束
level[l] += 1;
return;
}
for(int i=0; i<node[a].size(); i++){
if(maxlevel < l+1) //更新最大层数,最后要知道有几层才能输出每层的叶子结点数
maxlevel = l + 1;
dfs(node[a][i], l+1);
}
}
int main() {
cin >> n >> m;
for(int i=0; i<m; i++){
int root, number, ch;
cin >> root >> number;
for(int j=0; j<number; j++){
cin >> ch;
node[root].push_back(ch);
}
}
dfs(1, 0);
for(int i=0; i<maxlevel; i++)
cout << level[i] << " ";
cout << level[maxlevel] << endl;
}
bfs
#include<bits/stdc++.h>
using namespace std;
int n, m;
int maxlevel = 0;
vector<int> node[1000];
int level[1000], num[1000]; //level某点的层数,num某层的叶子节点数
void bfs(){
queue<int> leaf;
leaf.push(1);
level[1] = 0;
while(!leaf.empty()){
int k = leaf.front();
leaf.pop();
maxlevel = max(maxlevel, level[k]);
for(int i=0; i<node[k].size(); i++) {
leaf.push(node[k][i]);
level[node[k][i]] = level[k] + 1;
}
if(node[k].size() == 0)
num[level[k]] += 1;
}
}
int main() {
cin >> n >> m;
for(int i=0; i<m; i++){
int root, number, ch;
cin >> root >> number;
for(int j=0; j<number; j++){
cin >> ch;
node[root].push_back(ch);
}
}
bfs();
for(int i=0; i<maxlevel; i++)
cout << num[i] << " ";
cout << num[maxlevel] << endl;
}
1007 Maximum Subsequence Sum
求最大连续子序列和及头尾位置
⚠️注意题目要求当所有数字都为负数时,输出0以及头尾数字即可
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f
int main(){
int n, flag = 0;
cin >> n;
int a[10001];
for(int i=0; i<n; i++) {
cin >> a[i];
if(a[i] < 0) //判断是否所有数字都为负数
flag++;
}
int first = 0, sum = -1;
int temp = 0;
int l, r;
for(int i=0; i<n; i++){
temp += a[i];
if(temp < 0){ //若temp加上a[i]<0,说明对后面的序列没价值了,temp重置为0,头移到下一个
temp = 0;
first = i + 1;
}
else if(temp > sum){
sum = temp;
l = first;
r = i;
}
}
if(sum < 0)
sum = 0;
if(flag == n)
cout << "0 " << a[0] << " " << a[n-1] << endl;
else
cout << sum << " " << a[l] << " " << a[r] << endl;
}
1010 Radix
最大的坑就是在数据范围,采用二分法锁定进制范围
第一个测试点卡的就是这条long long high = max(s, low);
因为有可能一个数很小,而另一个数很大很大,用这个可以直接卡死范围
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f
//将radix进制的数b转化为long long型
long long change(string b, long long radix){
long long s = 0, k = 0;
for(int i=b.length()-1; i>=0; i--){
if(b[i] >= '0' && b[i] <= '9')
s += pow(radix, k++) * (b[i] - '0');
else
s += pow(radix, k++) * (b[i] - 87);
}
return s;
}
//找出转为10进制等于s的n的进制
long long find_index(string n, long long s){
char mmax = *max_element(n.begin(), n.end());
long long low = (isdigit(mmax) ? mmax - '0' : mmax - 87) + 1; //最小进制为最大的数字加1
long long high = max(s, low);
while(low <= high){
long long mid = (high + low) / 2;
long long t = change(n, mid);
if(t < 0 || t > s)
high = mid - 1;
else if(t == s)
return mid;
else
low = mid + 1;
}
return -1;
}
int main(){
string a, b;
long long tag, radix;
cin >> a >> b >> tag >> radix;
long long s;
s = tag == 1 ? find_index(b, change(a, radix)) : find_index(a, change(b, radix));
if(s != -1)
cout << s << endl;
else
cout << "Impossible" << endl;
}