訓練(一) 最短路、最小生成樹

A. 最小生成樹一·Prim算法 HihoCoder 1097

https://hihocoder.com/problemset/problem/1097

Prim算法模版題

#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
//#include <set>
//#include <queue>
//#include <iomanip>
//#include <map>
//#include <time.h>
using namespace std;
typedef long long ll;
inline int read() {
    int x = 0;int f = 1; char c = getchar();
    while(c<'0' || c>'9') {if(c=='-') f = -f; c = getchar();}
    while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
    return x*f;
}
inline void write(int x) {
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[36];int tot = 0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
//mt19937 rnd(time(NULL));
const int inf = 0x3f3f3f3f;
const int maxn = 1e3+5;
int num[maxn][maxn];
int dis[maxn];
bool vis[maxn];
int n;
void init(int n ) {
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            if(i == j) num[i][j] = 0;
            else num[i][j] = inf;
        }
    }
}

int prim(int a[][maxn]) {
    int ans = 0;
    memset(vis, false, sizeof(vis));
    vis[0] = true;
    for(int i = 1; i < n; i++)
        dis[i] = num[0][i];
    for(int i = 1; i < n; i++) {
        int minn = inf,u = -1;
        for(int j = 0; j < n; j++) {
            if(!vis[j] && dis[j] < minn) {
                minn = dis[j];
                u = j;
            }
        }
        if(ans == inf) return -1;
        ans += minn;
        vis[u] = 1;
        for(int k = 0; k < n; k++) {
            if(!vis[k]) dis[k] = min(dis[k],num[u][k]);
        }
    }
    return ans;
}
int a[maxn];
int main() {
    scanf("%d",&n);
    init(n);
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            scanf("%d",&num[i][j]);
        }
    }
    printf("%d\n",prim(num));

    return 0;
}

 

B. 最小生成樹二·Kruscal算法 https://hihocoder.com/problemset/problem/1098

Kruskal模版題

//這波要用到路徑壓縮,一定要

#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
//#include <set>
//#include <queue>
//#include <iomanip>
//#include <map>
//#include <time.h>
using namespace std;
typedef long long ll;
inline int read() {
    int x = 0;int f = 1; char c = getchar();
    while(c<'0' || c>'9') {if(c=='-') f = -f; c = getchar();}
    while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
    return x*f;
}
inline void write(int x) {
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[36];int tot = 0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
//mt19937 rnd(time(NULL));
const int inf = 0x3f3f3f3f;
const int maxn = 1e6+10;
int father[maxn/10 + 5];
int sum;
int N,M;
struct node{
    int u, v, w;
}edge[maxn];
void init(int n) {
    for(int i = 0; i < n; i++) {
        father[i] = i;
    }
}
int find(int x) {
    while(x!=father[x]) x=father[x] = father[father[x]];
    return x;
}
bool cmp(node a, node b) {
    return a.w < b.w;
}
int cnt;
void kruskal() {
    sort(edge,edge+M,cmp);
    for(int i = 0; i < M; i++) {
        int eu = find(edge[i].u),ev = find(edge[i].v);
        if(eu == ev) continue;
        sum += edge[i].w;
        father[ev] = eu;
        if(++cnt == N - 1) {break;}
    }
}

int main() {
    scanf("%d%d",&N,&M);
    for(int i = 0; i < M; i++){
        scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
    }
    init(N);
    kruskal();
    printf("%d\n",sum);
    return 0;
}

 

C.最短路(Dijkstra)

https://hihocoder.com/problemset/problem/1081

#include <iostream>
#include <cstring>
using namespace std;
const int N = 10001;
const int M = 100001;


struct edge {
    int v, w, next;
    edge(){}
    edge(int _v, int _w, int _next) {
        v = _v;
        w = _w;
        next = _next;
    }
} e[M * 2];

int head[N], size;

void init() {
    memset(head, -1, sizeof(head));
    size = 0; //邊數
}

void insert(int u, int v, int w) {
    e[size] = edge(v, w, head[u]);
    head[u] = size++;
}

void insert2(int u, int v, int w) {
    insert(u, v, w);
    insert(v, u, w);
}

int n, m;
int dis[N];
bool vis[N];
void dijkstra(int u) {
    memset(vis,false,sizeof(vis));
    memset(dis,0x3f,sizeof(dis));
    dis[u] = 0;
    for(int i = 0;i < n;++i) {
        int mind = 1000000000,minj = -1;
        for(int j = 1;j <= n; ++j){
            if(!vis[j] && dis[j] < mind) {
                minj = j;
                mind = dis[j];
            }
        }
        if(minj == -1) {
            return;
        }
        vis[minj] = true;
        for(int j = head[minj]; ~j; j = e[j].next) {
            int v = e[j].v;
            int w = e[j].w;
            if(!vis[v] && dis[v] > dis[minj] + w) {
                dis[v] = dis[minj] + w;
            }
        }
    }
}
int main() {
    init();
    int u, v, w;
    int ini,des;
    cin >> n >> m >> ini >> des;
    while(m--) {
        cin >> u >> v >> w;
        insert2(u, v, w);
    }
    dijkstra(ini);
    cout << dis[des] << endl;
    return 0;
}

 

D.最短路(Floyd)

https://hihocoder.com/problemset/problem/1089

#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <string>
#include <set>
#include <stack>
//#include <queue>
//#include <iomanip>
//#include <map>
//#include <time.h>
using namespace std;
typedef long long ll;
inline int read() {
    int x = 0;int f = 1; char c = getchar();
    while(c<'0' || c>'9') {if(c=='-') f = -f; c = getchar();}
    while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
    return x*f;
}
inline void write(int x) {
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[36];int tot = 0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
//mt19937 rnd(time(NULL));
const int inf = 0x3f3f3f3f;
const int maxn = 1e2+10;
int a[maxn][maxn];
int n, m;
int u,v,w;
int main() {
    cin >> n >> m;
    for(int i = 1; i <=n; i++) {
        for(int j = 1; j <= n; j++) {
            if(i == j) {a[i][j] = 0;}
            else {a[i][j] = inf;}
        }
    }
    for(int i = 1; i <= m; i++) {
        cin >> u >> v >> w;
        a[u][v] =a[v][u] = min(a[u][v],w);
    }
    
    for(int k = 1; k <= n; k++) {
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                a[i][j] = min(a[i][j],a[i][k] + a[k][j]);
            }
        }
    }
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= n;j ++) {
            cout << a[i][j] <<" ";
        }cout << endl;
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章