数据结构第四次上机实验报告

指导老师:Gu Fangming

-1 连通分量 (100 分)

无向图 G 有 n 个顶点和 m 条边。求 G 的连通分量的数目。

输入格式:

第1行,2个整数n和m,用空格分隔,分别表示顶点数和边数, 1≤n≤50000, 1≤m≤100000.

第2到m+1行,每行两个整数u和v,用空格分隔,表示顶点u到顶点v有一条边,u和v是顶点编号,1≤u,v≤n.

输出格式:

1行,1个整数,表示所求连通分量的数目。

代码长度限制

16 KB

时间限制

200 ms

内存限制

10 MB

老师和同学们的思路是用dfs或者bfs遍历来统计根节点个数,也可以运用集合的思想,使用并查集进行运算,统计父亲节点是自身的节点个数即可。

#include <iostream>
#include<stack>
using namespace std;
int father[50010];
int findfathere(int j) {
    while (father[j] != j)
        j = father[j];
    return j;
}
void uni(){
    int j, k;
    cin >> j >> k;
    father[findfathere(k)] = findfathere(j);
}
stack<int> pp;
int main()
{
    int n, m,sum=0;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        father[i] = i;
    for (int i = 1; i <= m; i++)
        uni();
    for (int t = 1; t <= n; t++) {
        int i = t; int z = 0;
        while (father[i] != i) {
            pp.push(i);
            i = father[i];
            z++;
        }
        while (z) {
            z--;
            father[pp.top()] = i;
            pp.pop();
        }
    }
    for (int i = 1; i <= n; i++) {
        if (father[i] == i) sum++;
    }
    cout << sum;
}

 

 

-2 整数拆分 (100 分)

整数拆分是一个古老又有趣的问题。请给出将正整数 n 拆分成 k 个正整数的所有不重复方案。例如,将 5 拆分成 2 个正整数的不重复方案,有如下2组:(1,4)和(2,3)。注意(1,4) 和(4,1)被视为同一方案。每种方案按递增序输出,所有方案按方案递增序输出。

输入格式:

1行,2个整数n和k,用空格分隔, 1≤k≤n≤50.

输出格式:

若干行,每行一个拆分方案,方案中的数用空格分隔。

最后一行,给出不同拆分方案的总数。

 思想就是走一步看一步(上一个数字确定了,下一个数字可取值的范围也就确定了)

以递归实现就好了,效率还是很高的。

#include <iostream>
using namespace std;
int n, k,sum = 0;
int dd[55]; int top = 1;
void output() {
    for (int i = 1; i <= k - 1; i++)
        cout << dd[i] << " ";
    cout << dd[k] << "\n";
}
void ddd(int deep,int max,int remain) {
    int t = remain / (k - deep + 1);
    if(deep!=k)
    for (int i = max; i <= t; i++) {
        dd[top] = i;
        top++;
        ddd(deep + 1, i, remain - i);
        }
    else {
        dd[deep] = remain;
        output();
        sum++;
    }
    top--;
}
int main()
{
    for (int i = 1; i <= 50; i++)
        dd[i] = 0;
    cin >> n >> k;
    ddd(1,1,n);
    cout << sum;
}


/*int dd[55];
    for (int i = 1; i <= 50; i++) {
        dd[i] = i;
    }*/

7-3 数字变换 (100 分)

利用变换规则,一个数可以变换成另一个数。变换规则如下:(1)x 变为x+1;(2)x 变为2x;(3)x 变为 x-1。给定两个数x 和 y,至少经过几步变换能让 x 变换成 y.

输入格式:

1行,2个整数x和y,用空格分隔, 1≤x,y≤100000.

输出格式:

第1行,1个整数s,表示变换的最小步数。

第2行,s个数,用空格分隔,表示最少变换时每步变换的结果。规则使用优先级顺序: (1),(2),(3)。

这题没啥说的,bfs找最短路,注意下边界问题就好了。

#include<queue>
#include <iostream>
#include<stack>
int dd[501010];
using namespace std;
queue<int> dui;
stack<int> lu;
int main()
{
    int x, y,sum=0;
    cin >> x >> y;
    if (x == y) {
        cout << "0";
        return 0;
    }
    for (int i = 1; i <= 501000; i++)
        dd[i] = 0;
    dui.push(x);
    while (!dd[y]){
        int j = dui.front();
        if(j<100010)
        {
        if (!dd[j + 1]) {
            dui.push(j + 1);
            dd[j + 1] = j;
        }
        if (!dd[j * 2]) {
            dui.push(j * 2);
            dd[j * 2] = j;
        }
        if (j - 1 > 0)
            if (!dd[j - 1]) {
                dui.push(j - 1);
                dd[j - 1] = j;
            }
    }
        dui.pop();
    }
    lu.push(y);
    while (lu.top()!=x) {
        lu.push(dd[lu.top()]);
        sum++;
    }
    lu.pop();
    cout << sum<<"\n";
    while (lu.size()>1) {
        cout << lu.top()<<" ";
        lu.pop();
    }
    cout << y;
}

 

 

7-4 旅行 I (100 分)

五一要到了,来一场说走就走的旅行吧。当然,要关注旅行费用。由于从事计算机专业,你很容易就收集到一些城市之间的交通方式及相关费用。将所有城市编号为1到n,你出发的城市编号是s。你想知道,到其它城市的最小费用分别是多少。如果可能,你想途中多旅行一些城市,在最小费用情况下,到各个城市的途中最多能经过多少城市。

输入格式:

第1行,3个整数n、m、s,用空格分隔,分别表示城市数、交通方式总数、出发城市编号, 1≤s≤n≤10000, 1≤m≤100000 。

第2到m+1行,每行三个整数u、v和w,用空格分隔,表示城市u和城市v的一种双向交通方式费用为w , 1≤w≤10000。

输出格式:

第1行,若干个整数Pi,用空格分隔,Pi表示s能到达的城市i的最小费用,1≤i≤n,按城市号递增顺序。

第2行,若干个整数Ci,Ci表示在最小费用情况下,s到城市i的最多经过的城市数,1≤i≤n,按城市号递增顺序。

 这道题就是信息量较多,dijiestra再加上一个找最长路的条件。

#include<vector>
#include <iostream>
#include<queue>
const int maxn = 200000000;
using namespace std;
int dist[10010];
int past[10010];
int guo[10010];
int last[10010];
vector<int> road[10010];
vector<int> cost[10010];
int main()
{
    int n, m, s;
    cin >> n >> m >> s;//n is city,m is traffic,s is start;
    for (int i = 1; i <= n; i++)
    {
        dist[i] = maxn;
        past[i] = 0;
        guo[i] = 0;
        last[i] = 0;
    }
    for (int i = 1; i <= m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        road[u].push_back(v);
        road[v].push_back(u);
        cost[u].push_back(w);
        cost[v].push_back(w);
    }
    dist[s] = 0;
    past[s] = 0;
    guo[s] = 1;
    last[s] = 0;
    for (int i = 0; i < road[s].size(); i++) {
        dist[road[s][i]] = cost[s][i];
        last[road[s][i]] = s;
    }
    for (int i = 1; i < n; i++) {
        int min = maxn+11;
        int tag;
        for (int t = 1; t <= n; t++) {
            if (!guo[t] && dist[t] < min) {
                tag = t;
                min = dist[t];
            }
            else if (!guo[t] &&dist[t] == min) {
                if (past[t] > past[tag]) {
                    tag = t;
                }
            }
        }
        guo[tag] = 1;
        past[tag] = past[last[tag]] + 1;
        for (int j = 0; j < road[tag].size(); j++) {
            if (dist[road[tag][j]] > dist[tag] + cost[tag][j]) {
                dist[road[tag][j]] = dist[tag] + cost[tag][j];
                last[road[tag][j]] = tag;
                past[road[tag][j]] = past[last[road[tag][j]]] + 1;
            }
            else if (dist[road[tag][j]] == dist[tag] + cost[tag][j]) {
                if (past[road[tag][j]] <= past[tag]) {
                    last[road[tag][j]] = tag;
                    past[road[tag][j]] = past[last[road[tag][j]]] + 1;
                }
               
            }
        }


    }
    for (int i = 1; i <= n; i++) {
        cout << dist[i];
        if (i == n)
            cout << "\n";
        else
            cout << " ";
    }
    for (int i = 1; i <= n; i++) {
        cout << past[i];
        if (i == n)
            ;
        else
            cout << " ";
    }


}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
很抱歉,我无法提供关于具体学校或课程的第四次上机内容。但是,我可以为您提供一些关于数据结构的基本知识和常见的上机题目类型。 数据结构是计算机科学中非常重要的一门课程,它研究如何组织和存储数据以及如何有效地操作和管理数据。第四次上机可能涉及以下内容之一: 1. 树和图的应用:树和图是常见的数据结构,可以用于解决各种实际问题,比如搜索、排序、最短路径等。在上机中,您可能需要实现树或图的基本操作,如插入、删除、遍历等。 2. 排序算法:排序是数据结构中的一个重要问题,常见的排序算法有冒泡排序、插入排序、选择排序、快速排序、归并排序等。您可能需要实现其中一个排序算法,并对给定的数据进行排序。 3. 查找算法:查找是另一个常见的问题,常见的查找算法有线性查找、二分查找、哈希查找等。您可能需要实现其中一个查找算法,并根据给定的条件查找特定的数据。 4. 动态规划:动态规划是一种解决最优化问题的方法,它将问题分解为子问题,并通过保存子问题的解来避免重复计算。您可能需要使用动态规划来解决给定的问题,并实现相应的算法。 以上只是一些可能的内容,具体的上机要求可能会根据课程教学大纲和教师的要求而有所不同。如果您有具体的问题或需要更详细的帮助,请提供更多信息,我将尽力回答您的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值