Logo Wy Online Judge

WyOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#454#80. 「NOIP2017」宝藏Pigsyy10024ms2012kbC++233.8kb2025-04-24 13:51:452025-04-24 13:51:47

answer

#include <cstdio>
//基础的头文件
#include <algorithm>
//给sort开的头文件
#define INF 1917483645
using namespace std;

int vis[20], lev[20], d[20];
//vis : 已经访问过的点
//lev : 点距离初始点的距离
//d : 通过此点可以达到的点数
int c[20][20], tar[20][20];
//c : 费用
//tar :存下每个点能到的点
/*为什么要特意存下每个点到的点?
答案其实并不困难,加快访问速度*/

int ans = INF, tmp, tot, cnt, n, m, p;
//ans : 最终的答案
//tmp : 最优解剪枝用
//tot : dfs储存中间答案的用具
//cnt :现在已经访问过的点数
//n : 点数
//m : 边数
//p : sort用品

inline bool cmp(int a, int b) {
    return c[p][a] < c[p][b];
    //按照费用给每个点能到的点排序
}

inline void dfs(int num, int node) {
    for (int i = num; i <= cnt; i ++) {
        //由第几个被访问的点来扩展
        if (tot + tmp * lev[vis[i]] >= ans)
            return;

        //最优性剪枝,如果当前解加上理论最小的费用都比中途的答案高
        //那么这次搜索一定不是最优解
        for (int j = node; j <= d[vis[i]]; j ++)

            //下一步扩展谁
            if (!lev[tar[vis[i]][j]]) { //用lev同时充当标记,有lev代表已访问
                cnt ++; //多添加一个点
                vis[cnt] = tar[vis[i]][j]; //记录这个点
                tmp -= c[vis[cnt]][tar[vis[cnt]][1]]; //理论最小的更新
                tot += c[vis[i]][vis[cnt]] * lev[vis[i]]; //加上当前的影响
                lev[vis[cnt]] = lev[vis[i]] + 1; //因为从vis[i]拓展,故lev一定为其 + 1
                dfs(i, j + 1); //继续从i枚举, 注意到tar[i][1 ~ j]已全部访问,下一次从j + 1尝试访问
                tot -= c[vis[i]][vis[cnt]] * lev[vis[i]]; //回溯
                lev[vis[cnt]] = 0; //回溯
                tmp += c[vis[cnt]][tar[vis[cnt]][1]]; //回溯
                cnt --; //回溯
            }

        node = 1; //剪枝别剪错了,i枚举玩下次还要从1枚举
    }

    if (cnt == n) { //已经访问了n个点,更新答案
        if (tot < ans)
            ans = tot;

        return;
    }
}

int main() {
    int u, v, w;
    scanf("%d%d", &n, &m); //读入n, m

    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= n; j ++)
            c[i][j] = INF; //初始赋无限大,方便后面的操作

    for (int i = 1; i <= m; i ++) {
        scanf("%d%d%d", &u, &v, &w); //这个w先暂时存起来

        //因为发现m = 1000 远> n * n,所以要剪掉一些边
        if (c[u][v] < w)
            continue; //w不能更新c[u][v]

        if (c[u][v] == INF) //第一次更新c[u][v],统计u,v的出度
            tar[u][++ d[u]] = v, tar[v][++ d[v]] = u;

        c[u][v] = c[v][u] = w;
    }

    for (int i = 1; i <= n; i ++) {
        p = i; //sort排序cmp
        sort(tar[i] + 1, tar[i] + 1 + d[i], cmp);
        tmp += c[i][tar[i][1]]; //因为每个点总要扩展一条边,
        //因此我们把最小的边找出来,作为最优性剪枝
        //不仅如此,因为边越小作为最终解的可能性越大
        //实际上在一定程度上优化了程序
    }

    for (int i = 1; i <= n; i ++) {
        tot = 0;
        cnt = 1; //赋初值
        vis[1] = i; //第一个就选i
        tmp -= c[i][tar[i][1]]; //i的最优性剪枝的影响要去掉
        //因为剪枝的时候是以还未访问和还未将被访问的点为基础的
        //不去掉剪枝就是错误的
        lev[i] = 1; //赋值
        dfs(1, 1); //只有一个点,也肯定是从1枚举
        lev[i] = 0; //回溯
        tmp += c[i][tar[i][1]];
    }

    printf("%d", ans);
    return 0;
}

详细

小提示:点击横条可展开更详细的信息

Test #1:

score: 5
Accepted
time: 1ms
memory: 1964kb

input:

1 0

output:

0

result:

ok "0"

Test #2:

score: 5
Accepted
time: 0ms
memory: 2012kb

input:

5 4
1 2 3
1 3 3
1 4 3
1 5 3

output:

12

result:

ok "12"

Test #3:

score: 5
Accepted
time: 0ms
memory: 1792kb

input:

8 7
1 2 3
2 3 3
3 4 3
4 5 3
5 6 3
6 7 3
7 8 3

output:

48

result:

ok "48"

Test #4:

score: 5
Accepted
time: 1ms
memory: 1752kb

input:

8 7
1 2 3
2 3 3
3 4 3
4 5 3
4 6 3
4 7 3
4 8 3

output:

30

result:

ok "30"

Test #5:

score: 5
Accepted
time: 1ms
memory: 1744kb

input:

8 20
6 8 4575
2 3 4575
5 6 4575
4 8 4575
8 1 4575
4 1 4575
3 6 4575
4 5 4575
4 5 4575
2 1 4575
7 8 4...

output:

45750

result:

ok "45750"

Test #6:

score: 5
Accepted
time: 0ms
memory: 1744kb

input:

7 79
2 1 1715
5 7 1715
4 6 1715
3 5 1715
3 4 1715
6 1 1715
1 2 1715
3 7 1715
2 1 1715
5 6 1715
4 7 1...

output:

10290

result:

ok "10290"

Test #7:

score: 5
Accepted
time: 1ms
memory: 1756kb

input:

6 26
1 5 93
4 5 93
1 2 93
6 3 93
4 6 93
1 2 93
6 1 93
6 2 93
1 4 93
3 4 93
4 3 93
6 2 93
1 4 93
5 2 ...

output:

465

result:

ok "465"

Test #8:

score: 5
Accepted
time: 1ms
memory: 1756kb

input:

7 47
5 1 808
4 3 808
5 2 808
2 7 808
2 4 808
3 1 808
5 1 808
4 2 808
5 4 808
5 6 808
3 1 808
1 2 808...

output:

4848

result:

ok "4848"

Test #9:

score: 5
Accepted
time: 2ms
memory: 1800kb

input:

5 806
5 1 4
3 5 2304
2 3 3533
5 2 4
5 1 1712
2 3 3760
4 1 144
5 2 2090
4 5 1603
1 4 862
5 3 2449
2 1...

output:

49

result:

ok "49"

Test #10:

score: 5
Accepted
time: 0ms
memory: 2012kb

input:

6 352
6 5 71
5 1 1591
2 4 106
6 2 3202
6 3 4021
2 4 132
4 2 1164
4 3 1102
2 1 2138
3 2 1755
1 3 1679...

output:

391

result:

ok "391"

Test #11:

score: 5
Accepted
time: 1ms
memory: 1864kb

input:

7 192
6 7 2992
4 1 2830
7 4 1972
2 3 4811
7 4 4400
4 3 1987
4 2 1205
5 1 1590
5 7 4824
2 6 1482
7 5 ...

output:

1037

result:

ok "1037"

Test #12:

score: 5
Accepted
time: 1ms
memory: 1804kb

input:

7 231
1 7 3862
1 6 1559
7 1 3538
2 6 2963
4 7 1170
3 7 1713
7 3 1737
6 7 409
2 5 2522
6 3 2412
2 3 2...

output:

1556

result:

ok "1556"

Test #13:

score: 5
Accepted
time: 1ms
memory: 1820kb

input:

8 196
2 7 3691
8 2 4425
5 8 4748
2 6 339
2 4 1368
1 5 55
6 3 3982
2 5 180
8 1 4436
4 8 4275
6 7 4204...

output:

649

result:

ok "649"

Test #14:

score: 5
Accepted
time: 2ms
memory: 1756kb

input:

8 324
5 7 4787
7 4 1110
3 4 4503
3 4 2527
2 7 1199
7 3 3660
5 1 982
7 2 1675
8 7 160
8 4 3790
7 5 35...

output:

630

result:

ok "630"

Test #15:

score: 5
Accepted
time: 2ms
memory: 1884kb

input:

11 793
1 6 267445
6 9 114589
11 7 356613
2 3 386762
1 3 262296
8 4 232142
7 3 60784
8 11 7827
7 5 16...

output:

78134

result:

ok "78134"

Test #16:

score: 5
Accepted
time: 3ms
memory: 1876kb

input:

11 988
8 1 298264
10 9 94456
9 1 348864
10 1 284796
11 6 203091
10 11 243084
7 1 34101
10 4 417170
4...

output:

58058

result:

ok "58058"

Test #17:

score: 5
Accepted
time: 1ms
memory: 1860kb

input:

12 110
10 8 349233
9 7 431229
3 2 23180
6 7 253401
10 7 376865
8 2 446361
4 9 474356
12 1 314737
6 1...

output:

690550

result:

ok "690550"

Test #18:

score: 5
Accepted
time: 0ms
memory: 1952kb

input:

12 294
2 3 343727
4 7 284269
10 4 146240
3 9 313885
5 6 366277
9 1 28701
7 8 329502
7 12 25620
6 1 5...

output:

190967

result:

ok "190967"

Test #19:

score: 5
Accepted
time: 2ms
memory: 1756kb

input:

12 769
11 1 269107
1 3 238993
6 11 218601
1 4 350327
8 12 23460
6 8 9637
3 7 292001
11 10 123618
6 9...

output:

76380

result:

ok "76380"

Test #20:

score: 5
Accepted
time: 4ms
memory: 1752kb

input:

12 763
11 5 332075
4 3 110459
5 11 412044
9 3 210419
11 1 53214
8 10 457467
6 3 47566
7 12 300566
9 ...

output:

123663

result:

ok "123663"