buct数据结构——图算法(最短路、最小生成树)

注:以下所有代码都没有在oj上提交,但是样例可以通过,如有错误,欢迎指正

问题 A: 图的最小生成树-Prim算法

#include <bits/stdc++.h>
using namespace std;
int w[110][110];
int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            cin >> w[i][j];
        }
    }
    for (int j = 0; j < n; j++)
    {
        if (w[0][j] == 0)
        {
            printf("%d - -\n", j);
        }
        else
        {
            printf("%d %d %d\n", j, w[0][j], 0);
        }
    }
    return 0;
}

问题 B: 图的最小生成树-Kruskal算法

#include <bits/stdc++.h> 
using namespace std; 
int n;
int w[110][110];
struct p
{
    int from,to,val;
};
vector<p>edge;
int main(){
    int n;
    cin>>n;
    for( int i=0;i<n;i++){
        for( int j=0;j<n;j++){
            cin>>w[i][j];
            if(w[i][j]==0) continue;
            edge.push_back((p){i,j,w[i][j]});
        }
    }
    for( int i=0;i<edge.size();i++){
        for( int j=i+1;j<edge.size();j++){
            if(edge[i].val>edge[j].val) swap(edge[j],edge[i]);
        }
    }
    for( int i=0;i<edge.size();i++){
        printf("<%d,%d>:%d\n",edge[i].from,edge[i].to,edge[i].val);
    }
    return 0;
}

问题 C: 算法7-9:最小生成树

#include <bits/stdc++.h> 
using namespace std;
const int N=60,inf=0x3f3f3f3f; 
int w[N][N];
int prim(int n){
    int vis[60]={};
    int dist[60];
    int res=0;
    memset(dist,0x3f,sizeof(dist));
    vis[0]=1;
    dist[0]=0;
    int now=0;
    for( int i=0;i<n-1;i++){
        for( int j=0;j<n;j++){
            if(w[now][j]==0||vis[j]==1) continue;
                dist[j]=min(dist[j],w[now][j]);
        }
        int ne=0;
        int minn=inf;
        for( int j=0;j<n;j++){
            if(vis[j])continue;
            if(dist[j]<minn){
                minn=dist[j];
                ne=j;
            }
        }
        res+=dist[ne];
        now=ne;
        vis[ne]=1;
    }
    return res;
    
}
int main(){
    int n;
    cin>>n;
    for( int i=0;i<n;i++){
        for( int j=0;j<n;j++){
            cin>>w[i][j];
        }
    }
    cout<<prim(n)<<endl;
    return 0;
}

问题 D: 算法7-15:迪杰斯特拉最短路径算法

#include <bits/stdc++.h> 
using namespace std;
const int N=60,inf=0x3f3f3f3f; 
int w[N][N];
int dist[N];
void dijistra(int n,int be){
    memset(dist,0x3f,sizeof(dist));
    int vis[N]={};
    vis[be]=1;
    dist[be]=0;
    int now=be;
    for( int i=0;i<n-1;i++){
        for( int j=0;j<n;j++){
            if(w[now][j]==0||vis[j]==1) continue;
            dist[j]=min(dist[j],dist[now]+w[now][j]);
        }
        int ne=0,minn=inf;
        for( int j=0;j<n;j++){
            if(vis[j]==1) continue;
            if(dist[j]<minn){
                minn=dist[j];
                ne=j;
            }
        }
        now=ne;
        vis[ne]=1;
    }  
    return ; 
}
int main(){
    int n;
    int be;
    cin>>n>>be;
    for( int i=0;i<n;i++){
        for( int j=0;j<n;j++){
            cin>>w[i][j];
        }
    }
    dijistra(n,be);
    for( int i=0;i<n;i++){
        if(i==be) continue;
        else cout<<dist[i]<<" ";
    }
    return 0;
}

问题 E: 图的最短路径-Floyd算法输出最短路径包含的边

#include <bits/stdc++.h> 
using namespace std;
const int N=110,inf=0x3f3f3f3f; 
struct p{
    int len,mid;
}w[N][N];
int main(){
    int n;
    cin>>n;
    for( int i=0;i<n;i++){
        for( int j=0;j<n;j++){
            cin>>w[i][j].len>>w[i][j].mid;
        }
    }
    int be,en;
    cin>>be>>en;
    stack<int>ans;
    cout<<w[be][en].len<<endl;
    while(true){
        ans.push(en);
        if(en==be) break;
        en=w[be][en].mid;
    }
    while(!ans.empty()){
        cout<<ans.top()<<" ";
        ans.pop();
    }
    return 0;
}

问题 F: 案例6-1.5:旅游规划

#include <bits/stdc++.h> 
using namespace std;
const int N=510,inf=0x3f3f3f3f; 
int h[N],ne[N*N],to[N*N],val[N*N],cost[N*N],cnt;
此处应为N*N,上一个版本写成N*2,现已修正
int n,m,s,d;
void add( int a,int b,int c,int d){
    cost[cnt]=d,val[cnt]=c,to[cnt]=b,ne[cnt]=h[a],h[a]=cnt++;
}
int dist[N];
int sum_cost[N];
void dijistra( int be){
    memset(dist,0x3f,sizeof(dist));
    memset(sum_cost,0x3f,sizeof(sum_cost));
    int vis[N]={};
    dist[be]=0;
    vis[be]=1;
    sum_cost[be]=0;
    int now=be;
    for( int i=0;i<n-1;i++){
        // cout<<now<<endl;
        for( int j=h[now];j!=-1;j=ne[j]){
            int k=to[j];
            if(vis[k]) continue;
            if(dist[k]>dist[now]+val[j]){
                dist[k]=dist[now]+val[j];
                sum_cost[k]=sum_cost[now]+cost[j];
            }
            else if(dist[k]==dist[now]+val[j]){
                sum_cost[k]=min(sum_cost[k],sum_cost[now]+cost[j]);
            }
        }
        int ne=0,min_dist=inf,min_cost=inf;
        for( int j=0;j<n;j++){
            if(vis[j]) continue;
            if(dist[j]<min_dist){
                min_dist=dist[j];
                min_cost=sum_cost[j];
                ne=j;
            }
            else if(dist[j]==min_dist&&sum_cost[j]<min_cost){
                min_cost=sum_cost[j];
                ne=j;
            }
        }
        vis[ne]=1;
        now=ne;
    }
}
int main(){
    memset(h,-1,sizeof(h));
    cin>>n>>m>>s>>d;
    for( int i=1;i<=m;i++){
        int a,b,c,d;
        cin>>a>>b>>c>>d;
        add(a,b,c,d);
        add(b,a,c,d);
    }
    dijistra(s);
    cout<<dist[d]<<" "<<sum_cost[d]<<endl;
    return 0;
}

问题 G: 案例6-1.7:公路村村通

#include <bits/stdc++.h> 
using namespace std;
const int N=1010,inf=0x3f3f3f3f; 
struct edge{
    int from,to,val;
};
vector<edge>e;
int fa[N];
int find( int x){
    if(x!=fa[x]) fa[x]=find(fa[x]);
    return fa[x];
}
void merge( int x,int y){
    if(find(x)!=find(y)){
        fa[find(x)]=find(y);
    }
}
bool cmp(edge a,edge b){
    return a.val<b.val;
}
int check(int n){
    for( int i=1;i<=n;i++){
        if(find(i)!=find(1)) return 0;
    }
    return 1;
}
int main(){
    int n,m;
    cin>>n>>m;
    for( int i=0;i<=n;i++) fa[i]=i;
    for( int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        e.push_back((edge){a,b,c});
    }
    sort(e.begin(),e.end(),cmp);
    int ans=0;
    for( int i=0;i<e.size();i++){
        if(find(e[i].from)!=find(e[i].to)){
            merge(e[i].from,e[i].to);
            ans+=e[i].val;
        }
    }
    if(check(n)==0) {
        cout<<-1<<endl;
    }
    else cout<<ans<<endl;
    return 0;
}

问题 H: 基础实验6-2.5:城市间紧急救援

#include <bits/stdc++.h> 
using namespace std;
const int inf=0x3f3f3f3f,N=510;
int n,m,s,d;
int w[N][N];
int call_num[N],path_num[N];
int pre[N],num[N];
void dijistra(){
    int vis[510],dist[510];
    memset(dist,0x3f,sizeof(dist));
    memset(pre,-1,sizeof(pre));
    vis[s]=1;
    dist[s]=0;
    call_num[s]=num[s];
    path_num[s]=1;
    int now=s;
    for( int i=1;i<n;i++){
        for( int j=0;j<n;j++){
            if(w[now][j]==0||vis[j]==1) continue;
            if(dist[j]>dist[now]+w[now][j]){
                dist[j]=dist[now]+w[now][j];
                call_num[j]=call_num[now]+num[j];
                path_num[j]=path_num[now];
                pre[j]=now;
            }
            else if(dist[j]==dist[now]+w[now][j]){
                if(call_num[j]<call_num[now]+num[j]){
                    call_num[j]=max(call_num[j],call_num[now]+num[j]);
                    pre[j]=now;
                }
                path_num[j]+=path_num[now];
            }
        }
        int minn=inf,ne=0;
        for( int j=0;j<n;j++){
            if(vis[j]==1) continue;
            if(dist[j]<minn){
                minn=dist[j];
                ne=j;
            }
            else if(dist[j]==minn&&num[j]>num[ne]){
                ne=j;
            }
        }
        vis[ne]=1;
        now=ne;
    }
}
int main(){
    cin>>n>>m>>s>>d;
    for( int i=0;i<n;i++) cin>>num[i];
    for( int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        w[a][b]=c;
        w[b][a]=c;
    }
    dijistra(); 
    stack<int>ans;
    cout<<path_num[d]<<" "<<call_num[d]<<endl;
    上面这句话位置写错,原来写在了while下面,现在已经修正
    while(d!=-1&&d!=s){
        ans.push(d);
        d=pre[d];
    }

    cout<<d<<" ";
    while(!ans.empty()){
        cout<<ans.top()<<" ";
        ans.pop();
    }
    return 0;
}

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值