其他分享
首页 > 其他分享> > 20200715模拟赛3题解

20200715模拟赛3题解

作者:互联网

A. 中中救援队

题目描述

输入格式

输出格式

样例输入

5 7
6
5
13
8
18
4 1 7
5 2 5
1 5 16
2 3 20
3 1 18
4 3 12
2 4 15

样例输出

154

数据范围与提示

Solve

Code

#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1e4+5, M = 1e5+5;
struct Node {
    int x, y, d;
    bool operator < (const Node &b) const {
        return d < b.d;
    }
}a[M];
int n, m, w[N], f[N], s = 1<<30;
int found(int x) {//并查集
    return f[x] == x ? x : (f[x] = found(f[x]));
}
int Kru() {
    int ans = 0, cnt = 0;
    sort(a + 1, a + m + 1);
    for (int i = 1; i <= n; ++i)
        f[i] = i;
    for (int i = 1; i <= m; ++i) {
        int x = found(a[i].x), y = found(a[i].y);
        if (x == y) continue;
        f[x] = y;
        ans += a[i].d;
        if (++cnt == n - 1) return ans;
    }
}
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i)
        scanf("%d", &w[i]), s = min(s, w[i]);
    for (int i = 1; i <= m; ++i)
        scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].d),
        a[i].d = a[i].d * 2 + w[a[i].x] + w[a[i].y];//这里最重要
    printf("%d\n", Kru() + s);
    return 0;
}

B. 家务活

题目描述

输入格式

输出格式

样例输入

7
5 0
1 1 1
3 1 2
6 1 1
1 2 2 4
8 2 2 4
4 3 3 5 6
```cpp
样例输出
```cpp
23

数据范围与提示

Solve

Code

#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1e4+5;
int n, f[N], ans;
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        int t, k, x;
        scanf("%d%d", &t, &k);
        while (k--) {
            scanf("%d", &x);
            f[i] = max(f[i], f[x]);
        }
        f[i] += t;
        ans = max(ans, f[i]);
    }
    printf("%d\n", ans);
    return 0;
}

C. 传纸条

题目描述

输入格式

输出格式

样例输入

3 3
0 3 9
2 8 5
5 7 0

样例输出

34

数据范围与提示

Solve

Code

#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 60;
int n, m, f[N<<1][N][N], a[N][N];
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            scanf("%d", &a[i][j]);
    for (int k = 3; k < n + m; ++k)
        for (int i = 1; i <= min(n, k); ++i)//这里和下面没取min就是我WA90的原因
            for (int j = i + 1; j <= min(n, k); ++j)
                f[k][i][j] = max(max(f[k-1][i][j], f[k-1][i-1][j-1]), max(f[k-1][i-1][j], f[k-1][i][j-1])) + a[i][k-i] + a[j][k-j];
    printf("%d\n", f[n+m-1][n-1][n]);
    return 0;
}

D. 杀人游戏

题目描述

输入格式

输出格式

样例输入

5 4 
1 2 
1 3 
1 4 
1 5 

样例输出

0.800000

数据范围与提示

Solve

Code1

//第一种方法
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5+5;
struct Side {
    int t, next;
}e[N*3];
int head[N], tot;
void Add(int x, int y) {//加边
    e[++tot] = (Side) {y, head[x]};
    head[x] = tot;
}
int n, m, d[N], s, ans;
bool v[N], f;
void Dfs(int x) {//染色
    s--;
    v[x] = 1;
    for (int i = head[x]; i; i = e[i].next)
        if (!v[e[i].t]) Dfs(e[i].t);
}
int main() {
    scanf("%d%d", &n, &m);
    s = n;
    while (m--) {//建立单向边并统计入度
        int x, y;
        scanf("%d%d", &x, &y);
        Add(x, y);
        ++d[y];
    }
    for (int i = 1; i <= n && s; ++i) {//正向遍历入度为0的点
        if (d[i]) continue;
        int l = s;
        Dfs(i);
        ++ans;
        if (l - s == 1) f = 1;//l-s是本次染色染了几个点
    }
    memset(v, 0, sizeof(v));
    ans = 0; 
    s = n;//进行初始化
    for (int i = n; i && s; --i) {//反向遍历入度为0的点
        if (d[i]) continue;
        int l = s;
        Dfs(i);
        ++ans;
        if (l - s == 1) f = 1;//同上
    }
    for (int i = 1; i <= n && s; ++i) {//遍历在环中的点
        if (v[i]) continue;
        int l = s;
        Dfs(i);
        ++ans;
        if (l - s == 1) f = 1;//同上
    }
    if (f) --ans;//如果有孤立点就有一个人可以不用询问
    printf("%.6lf", (double)(n - ans) / n);
    return 0;
}

Code2

//第二种方法
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1e5+5;
struct Side {
    int t, next;
}e[N*3];
int head[N], tot;
void Add(int x, int y) {
    e[++tot] = (Side) {y, head[x]};
    head[x] = tot;
}
int n, m, d[N], s, ans;
bool v[N], f;
bool judge(int x) {//如果返回0,则这个点可以当作孤立点,要在第二次for循环中遍历
    for (int i = head[x]; i; i = e[i].next)
        if (d[e[i].t] != 1) return 0;
    return 1;
}
void Dfs(int x) {//染色
    s--;
    v[x] = 1;
    for (int i = head[x]; i; i = e[i].next)
        if (!v[e[i].t]) Dfs(e[i].t);
}
int main() {
    scanf("%d%d", &n, &m);
    s = n;
    while (m--) {//建单向边,统计入度
        int x, y;
        scanf("%d%d", &x, &y);
        Add(x, y);
        ++d[y];
    }
    //第一次遍历入度为0且他的子节点只有他这唯一的父节点
    for (int i = 1; i <= n && s; ++i) {
        if (d[i] || !judge(i)) continue;
        int l = s;
        Dfs(i);
        ++ans;
        if (l - s == 1) f = 1;
    }
    //第二次遍历入度为0且他的子节点不只有他这唯一的父节点
    for (int i = 1; i <= n && s; ++i) {
        if (d[i] || v[i]) continue;//这里添了一个v是不要去遍历第一个循环遍历过的点
        int l = s;
        Dfs(i);
        ++ans;
        if (l - s == 1) f = 1;
    }
    //第三次遍历在环中的点
    for (int i = 1; i <= n && s; ++i) {
        if (v[i]) continue;
        int l = s;
        Dfs(i);
        ++ans;
        if (l - s == 1) f = 1;
    }
    if (f) --ans;
    printf("%.6lf", (double)(n - ans) / n);
    return 0;
}

标签:20200715,head,小轩,int,题解,中中,杀手,include,模拟
来源: https://www.cnblogs.com/Z8875/p/13331523.html