拓扑排序

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int a[101][101],c[101],r[101],ans[101];

int E;
int head[100010];
int to[100010];
int nxt[100010];
void add_edge(int a, int b)
{
    to[E] = b;
    nxt[E] = head[a];
    head[a] = E;
    E ++;
}

void init()
{
    E = 0;
    memset(head, -1, sizeof head);
}

int i,j,tot,temp,num,n,m;
int main() {
    init();
    cin >> n;
    for (i = 1; i <= n; i++) {
        do {
            cin >> j;
            if (j !=0 ) {
                c[i]++;
                add_edge(i, j);
                r[j]++;
            }
        } while (j != 0);
    }
    for (i=1;i<=n;i++)
        if (r[i] == 0)
            ans[++tot] = i;
    do {
        temp = ans[tot];
        cout << temp << " ";
        tot--;
        num++;
        for (i = head[temp]; i != -1; i=nxt[i]) {
            r[to[i]]--;
            if (r[to[i]] == 0) 
                ans[++tot] = to[i];
        }
    } while (num != n);
    return 0;
}

最短路

Dijkstra-邻接表

#include<iostream>
#include<cstring>
using namespace std;
const int maxn=101;
int f[maxn],d[maxn],path[maxn];
int n,m,start;
int head[1001],num_edge;
struct Edge {
    int next;
    int to;
    int w;
} edge[1001];
const int inf=99999;
void add_edge(int from,int to,int w) {
    edge[++num_edge].next=head[from];
    edge[num_edge].to=to;
    edge[num_edge].w=w;
    head[from]=num_edge;
}
void init() {
    cin>>n>>m>>start;
    int x,y,w;
    for(int i=1; i<=m; i++) {
        cin>>x>>y>>w;
        add_edge(x,y,w);
        add_edge(y,x,w);
    }
}
void dijkstra(int s) {
    for (int i=1; i<=n; i++)  {
        d[i]=inf;
        f[i]=false;
    }
    d[s]=0;
    for (int i=1; i<=n; i++) {
        int mind=inf;
        int k;//用来记录准备放入集合1的点
        for (int j=1; j<=n; j++) //查找集合2中d[]最小的点
            if  ( (!f[j]) &&(d[j]<mind) ) {
                mind=d[j];
                k=j;
            };
        if  (mind==inf)  break; //更新结点求完了
        f[k]=true;   // 加入集合1
        int j=head[k];//修改集合2中的d[j]
        while(j!=0) {
            int t=edge[j].to;
            if(!f[t] && d[k]+edge[j].w<d[t]) {
                d[t]=d[k]+edge[j].w;
                path[t]=k;
            }
            j=edge[j].next;
        }        
    }
}
void dfs(int i) {
    if(i!=start) dfs(path[i]);
    cout<<i<<' ';
}
void write() {
    for (int i=1; i<=n; i++)
        if(i!=start) {
            dfs(i);
            cout<<d[i]<<endl;
        }
}
int main() {
    init();
    dijkstra(start);
    write();
    return 0;
}

spfa 邻接表

#include <iostream>
#include<cstdio>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn=1001,maxm=100001;
struct Edge {
    int next; //下一条边的编号
    int to; //这条边到达的点
    int w;
} edge[maxm];

int g[maxn],num_edge,n,m,s;
int dis[maxn],pre[maxn],team[maxn],head,tail;
bool f[maxn];

void add_edge(int from,int to,int w) { //加入一条从from到to的单向边
    edge[++num_edge].next=g[from];
    g[from]=num_edge;
    edge[num_edge].to=to;
    edge[num_edge].w=w;
}

void init() {
    int u,v,w;
    num_edge=0;
    scanf("%d %d %d",&n,&m,&s);//读入点数和边数
    for(int i=1; i<=m; i++) {
        scanf("%d %d %d",&u,&v,&w);
        //u、v之间有一条边
        add_edge(u,v,w);
        add_edge(v,u,w);
    }
}

void SPFA() {
    for (int i=1; i<=n; i++) dis[i]=INF;
    dis[s]=0;
    head=0;
    tail=1;
    team[0]=s;
    f[s]=true;
    while(head<tail) {
        int u=team[head++];
        f[u]=false;
        for (int i=g[u]; i!=0; i=edge[i].next) {
            int v=edge[i].to;
            if (dis[v]>dis[u]+edge[i].w) {
                dis[v]=dis[u]+edge[i].w;
                pre[v]=u;
                if (!f[v]) { //队列中不存在v点,v入队。
                    team[tail++]=v;
                    f[v]=true;
                }
            }
        }
    }
}

void dfs(int i) {
    if(i!=s) dfs(pre[i]);
    cout<<i<<' ';
}
void write() {
    for (int i=1; i<=n; i++)
        if(i!=s) {
            dfs(i);
            cout<<dis[i]<<endl;
        }
}

int main() {

    init();
    SPFA();
    write();
    /*for (int u=1;u<n;u++)
    {
        cout<<u<<' ';
        for (int i=g[u];i!=0;i=edge[i].next)
        {
            int v=edge[i].to;
            cout<<v<<' ';
        }
        cout<<endl;
    }*/
    return 0;
}

/*
5 8 1
1 2 10
1 5 7
1 3 49
2 3 17
2 4 7
2 5 5
3 4 34
4 5 13
*/

最小生成树

kruskal

#include<bits/stdc++.h>
using namespace std;
#define N 105
#define INF 0x3f3f3f3f
struct edge {
    int u;
    int v;
    int w;
};
struct edge e[N];
int n,m;
int f[N];
int sum=0,num=0;
int cmp(const edge &a,const edge &b) {
    if(a.w<b.w) return 1;
    else return 0;
}
int getf(int v) {
    if(f[v] == v) {
        return v;
    } else {
        f[v] = getf(f[v]);//路径压缩
        return f[v];
    }
}
int merge(int v,int u) {
    int t1,t2;
    t1=getf(v);
    t2=getf(u);
    if(t1!=t2) { //不在同一集合
        f[t2] = t1;
        return 1;
    }
    return 0;
}
int main() {
    int i;
    cin>>n>>m;
    for(i=1; i<=m; i++) {
        cin>>e[i].u>>e[i].v>>e[i].w;
    }
    sort(e+1,e+m+1,cmp);
    //init
    for(i=1; i<=n; i++) {
        f[i] = i;
    }
    //Kruskal
    for(i=1; i<=m; i++) {
        if(merge(e[i].u,e[i].v)) {
            num++;//选边数
            sum=sum+e[i].w;//权值和
        }
        if(num==n-1) break;
    }
    cout<<sum;
    return 0;
}

prim

#include<bits/stdc++.h>
using namespace std;
#define N 105
#define INF 0x3f3f3f3f

int main(){
    int n,m,i,j,k,min,t1,t2,t3;
    int e[N][N],dis[N],book[N]={0};
    int num=0,sum=0;
    cin>>n>>m;
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++){
            if(i==j) e[i][j] = 0;
            else e[i][j] = INF;
        }
    }
    //read
    for(i=1;i<=m;i++){
        cin>>t1>>t2>>t3;
        e[t1][t2]=t3;
        e[t2][t1]=t3;//无向图 
    } 
    for(i=1;i<=n;i++) dis[i]=e[1][i];
    //prim
    book[1] = 1;
    num++;
    while(num<n){
        min = INF;
        for(i=1;i<=n;i++){
            if(book[i]==0 && dis[i]<min){
                min = dis[i];
                j = i;
            }
        }
        book[j] = 1;
        num++;
        sum += dis[j];
        for(k=1;k<=n;k++){
            if(book[k] == 0 && dis[k]>e[j][k]){
                dis[k] = e[j][k];
            }
        }
    } 
    cout<<sum;
    return 0;
}

 

posted on 2022-08-21 11:36  ljq0120  阅读(18)  评论(0)    收藏  举报