2021-05-26

吉林大学数据结构 荣誉课 上机实验4

无向图 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个整数,表示所求连通分量的数目。

输入样例:

在这里给出一组输入。例如:

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

输出样例:

在这里给出相应的输出。例如:

2

 思路一:用DFS算法遍历图,并用visit数组标志遍历过的节点,因为每次用DFS算法只能遍历一个连通分量,用循环计数来计算连通分支数量,当所有节点都遍历过后输出连通分支数量。

代码一:

#include <vector>
#include <iostream>
#include <cstdio>
using namespace std;
vector<int> s[50010];
int n, m;
int sum = 0;
int x, y;
int visit[50010] = { 0 };
void DFS(int k) {
    visit[k] = 1;
    for (vector<int>::iterator it = s[k].begin(); it != s[k].end(); it++) {
        if (visit[*it] == 0) {
            DFS(*it);
        }
    }
}
int main() {
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        cin >> x >> y;
        s[x].push_back(y);
        s[y].push_back(x);
    }
    for (int i = 1; i <= n; i++) {
        if (visit[i] == 0) {
            DFS(i);
            sum++;
        }
    }
    printf("%d", sum);
}

思路二:

并查集,如果两个节点属于同一个连通分量,可以用并查集把他们合并,最后遍历所有节点,入锅节点所在集合的标志元素是他本身,就为一个连通分量。

代码二:

#include <bits/stdc++.h>
using namespace std;
int n,m;
int sum=0;
int res[50010]={0};
int find(int x){
if(res[x]==x)
return x;
return find(res[x]);
}
int combine(int x,int y){
int a=find(x);
int b=find(y);
if(a!=b)
res[b]=a;
}
int main(){
int x,y;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
res[i]=i;
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
combine(x,y);
}
for(int i=1;i<=n;i++){
if(res[i]==i)
sum++;
}
printf("%d",sum);
}

7-2 整数拆分 (100 分)

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

输入格式:

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

输出格式:

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

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

输入样例:

在这里给出一组输入。例如:

5 2

输出样例:

在这里给出相应的输出。例如:

1 4
2 3
2

思路:这道题求满足某种约束条件的全部解,常常采用回溯法;

首先确定状态变量,作为判断回溯是否结束的标记,a为分解当前数字剩下的变量,b为存储最新分解结果的数组下标的后一位,b用于判断分解是否符合题中要求,假设输入的分解数字是n,分别确定res[1]为1到n的所有整数,调用回溯法,即toys(n-i,2);如果a==0或者b>=k+1结束回溯,判断结果是否符合题意并输出,否则将上一次分解结果作为i的初值,i<=a,继续用回溯法回溯,寻找结果。

#include <bits/stdc++.h>
using namespace std;
int x,y,sum=0;
int res[10000];
void toys(int a,int b){
    if(a==0&&b!=y+1)return ;
    if(a!=0&&b==y+1)return ;
    if(a==0&&b==y+1){
        sum++;
        printf("%d",res[1]);
        for(int i=2;i<=y;i++){
            printf("% d",res[i]);
        }
        printf("\n");
        return ;
    }
    for(int i=res[b-1];i<=a;i++){
        res[b]=i;
        toys(a-i,b+1);
    }
}
int main(){
    scanf("%d%d",&x,&y);
    for(int i=1;i<=x;i++){
        res[1]=i;
        toys(x-i,2);
    }
    printf("%d",sum);

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)。

输入样例:

在这里给出一组输入。例如:

2 14

输出样例:

在这里给出相应的输出。例如:

4
3 6 7 14

 解题思路:此题要将x通过给定的优先级确定的运算转换成y,仔细分析转换过程中的数字包括x,y都对应3条路,是三种运算构成的路,所以此题为求BFS问题,利用队列队列辅助遍历,path数组储存路径,同时过程中注意更新计算最短步数的变量。

#include <bits/stdc++.h>
using namespace std;
queue<int> s;
int x,y;
int visit[100010]={0},path[100010]={0},f[100010],resu[100010];
void toys(){
    while(!s.empty()){
        int a=s.front();
        s.pop();
        if(a==y)
        return ;
        if(!visit[a+1]&&a+1<=100000&&a+1>=1){
            visit[a+1]=1;
            s.push(a+1);
            path[a+1]=a;
            f[a+1]=f[a]+1;
        }
        if(!visit[a*2]&&a*2<=100000&&a*2>=1){
            visit[a*2]=1;
            s.push(a*2);
            path[a*2]=a;
            f[a*2]=f[a]+1;
        }
        if(!visit[a-1]&&a-1<=100000&&a-1>=1){
            visit[a-1]=1;
            s.push(a-1);
            path[a-1]=a;
            f[a-1]=f[a]+1;
        }
    }
}
int main(){
    int h=0;
    int c=0;
    scanf("%d%d",&x,&y);
    path[x]=0;
    visit[x]=1;
    s.push(x);
    toys();
    printf("%d\n",f[y]);
     h=y;
    while(h){
        resu[++c]=h;
        h=path[h];
    }
    for(int i=f[y];i>=1;i--){
        printf("%d",resu[i]);
        if(i!=1)printf(" ");
    }
    return 0;
}

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,按城市号递增顺序。

输入样例:

在这里给出一组输入。例如:

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

输出样例:

在这里给出相应的输出。例如:

0 2 6 5 13
0 1 2 1 3

解题思路:

典型的最短路问题,利用Dijkstra算法,同时注意用数组储存最佳路径路过的城市数。 

#include<cstdio>
#include<cctype>
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int inf = 9999999;
struct edge{
    int nxt, to, val;
}e[200010];
int n, m, s, head[200010], vis[100010], dis[100010], rd[100010];
int tot = 0;
queue<int> q;
 void add( int u,  int v,  int w){
    e[++tot].nxt = head[u];
    e[tot].to = v;
    e[tot].val = w;
    head[u] = tot;
}
 void SPFA(){
    while(!q.empty()){
        int u = q.front();
        q.pop();
        vis[u] = 0;
        for( int i = head[u]; i; i = e[i].nxt){
            int v = e[i].to;
            if(dis[v] > dis[u] + e[i].val){
                dis[v] = dis[u] + e[i].val;
                rd[v] = rd[u] + 1;
                if(!vis[v]){
                    vis[v] = 1;
                    q.push(v);
                }
            } else if(dis[v] == dis[u] + e[i].val){
                rd[v] = max(rd[v], rd[u] + 1);
            }
        }
    }
}
int main(){
    int u,v,w;
scanf("%d%d%d",&n,&m,&s);
    for( int i = 1; i <= m; ++i){
        scanf("%d%d%d",&u,&v,&w);
        add(u, v, w);
        add(v, u, w);
    }
    for( int i = 1; i <= n; ++i)    dis[i] = inf, vis[i] = 0, rd[i] = 0;
    dis[s] = 0;
    q.push(s);
    SPFA();
    for(int i = 1; i <= n; ++i){
        printf("%d", dis[i]);
        if(i != n)    printf(" ");
        else    printf("\n");
    }
    for( int i = 1; i <= n; ++i){
        printf("%d", rd[i]);
        if(i != n)    printf(" ");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
2021-03-26 20:54:33,596 - Model - INFO - Epoch 1 (1/200): 2021-03-26 20:57:40,380 - Model - INFO - Train Instance Accuracy: 0.571037 2021-03-26 20:58:16,623 - Model - INFO - Test Instance Accuracy: 0.718528, Class Accuracy: 0.627357 2021-03-26 20:58:16,623 - Model - INFO - Best Instance Accuracy: 0.718528, Class Accuracy: 0.627357 2021-03-26 20:58:16,623 - Model - INFO - Save model... 2021-03-26 20:58:16,623 - Model - INFO - Saving at log/classification/pointnet2_msg_normals/checkpoints/best_model.pth 2021-03-26 20:58:16,698 - Model - INFO - Epoch 2 (2/200): 2021-03-26 21:01:26,685 - Model - INFO - Train Instance Accuracy: 0.727947 2021-03-26 21:02:03,642 - Model - INFO - Test Instance Accuracy: 0.790858, Class Accuracy: 0.702316 2021-03-26 21:02:03,642 - Model - INFO - Best Instance Accuracy: 0.790858, Class Accuracy: 0.702316 2021-03-26 21:02:03,642 - Model - INFO - Save model... 2021-03-26 21:02:03,643 - Model - INFO - Saving at log/classification/pointnet2_msg_normals/checkpoints/best_model.pth 2021-03-26 21:02:03,746 - Model - INFO - Epoch 3 (3/200): 2021-03-26 21:05:15,349 - Model - INFO - Train Instance Accuracy: 0.781606 2021-03-26 21:05:51,538 - Model - INFO - Test Instance Accuracy: 0.803641, Class Accuracy: 0.738575 2021-03-26 21:05:51,538 - Model - INFO - Best Instance Accuracy: 0.803641, Class Accuracy: 0.738575 2021-03-26 21:05:51,539 - Model - INFO - Save model... 2021-03-26 21:05:51,539 - Model - INFO - Saving at log/classification/pointnet2_msg_normals/checkpoints/best_model.pth 我有类似于这样的一段txt文件,你帮我写一段代码来可视化这些训练结果
02-06

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值