zoukankan      html  css  js  c++  java
  • 无向图最小环

    【题目描述】:

    给定一张无向图,求图中一个至少包含 3个点的环,环上的节点不重复,并且环上的边的长度之和最小。该问题称为无向图的最小环问题。在本题中,你需要输出最小环的边权之和。若无解,输出 “No solution.”。图的节点数不超过 100。

    【输入描述】:

    第一行两个正整数 n,m表示点数和边数。

    接下来 m行,每行三个正整数 x,y,z,表示节点 x,y之间有一条长度为 z的边。

    【输出描述】:

    输出一个最小环的边权之和。若无解,输出 “No solution.”

    【样例输入】: 5 7 1 4 1 1 3 300 3 1 10 1 2 16 2 3 100 2 5 15 5 3 20

    【样例输出】: 61

    【时间限制、数据范围及描述】:

    时间:1s 空间:512M

    对于 20%的数据:1<=n<=10;

    对于100%的数据:1<=n<=100;边权<=300。

    对着floyd的模板打了半天,感觉for循环好多···

    不过这道题模板改改就能用。

    (不要纠结数组为什么是dijsktra的缩写)

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    const int MAX=105;
    const int oo=100000000;
    int n,m;
    int dist[MAX][MAX],a[MAX][MAX];
    int s[MAX][MAX];
    int ans[MAX];
    int hh;
    inline int mn(int x,int y){return x<y?x:y;}
    inline int mx(int x,int y){return x>y?x:y;}
    void init(){
        int i,j;
        int u,v,w;
        for (i=1;i<=n;i++){
            for (j=1;j<=n;j++){
                dist[i][j]=a[i][j]=(i==j?0:oo);
            }
        }
        mem(s,0);
        ans[0]=0;
        for (i=1;i<=m;i++){
            scanf("%d%d%d",&u,&v,&w);
            a[u][v]=mn(a[u][v],w);
            dist[u][v]=dist[v][u]=a[v][u]=a[u][v];
        }
    }
    void dfs(int u,int v){
        int k=s[u][v];
        if (k==0){
            ans[++ans[0]]=v;
            return;
        }
        dfs(u,k);
        dfs(k,v);
    }
    void floyd(){
        int i,j,k;
        hh=oo;
        for (k=1;k<=n;k++){
            for (i=1;i<k;i++){
                for (j=i+1;j<k;j++){
                    if (dist[i][j]+a[i][k]+a[k][j]<hh){
                        hh=dist[i][j]+a[i][k]+a[k][j];
                        ans[0]=0;
                        ans[++ans[0]]=i;
                        dfs(i,j);
                        ans[++ans[0]]=k;
                    }
                }
            }
            for (i=1;i<=n;i++){
                for (j=1;j<=n;j++){
                    if (dist[i][j]>dist[i][k]+dist[k][j]){
                        s[i][j]=k;
                        dist[i][j]=dist[i][k]+dist[k][j];
                    }
                }
            }
        }
    }
    int main(){
        freopen ("trip.in","r",stdin);
        freopen ("trip.out","w",stdout);
        init();
        int i,j;
        while (~scanf("%d%d",&n,&m)){
            init();
            floyd();
            if (hh==oo){
                puts("No solution.");
            }
            else{
                for (i=1;i<ans[0];i++){ 
                    printf("%d ",ans[i]);
                }
                printf("%d
    ",ans[i]);
            }
        }
        return 0;
    }
  • 相关阅读:
    【leetcode刷题笔记】Merge Intervals
    【leetcode刷题笔记】Implement strStr()
    【leetcode刷题笔记】Rotate List
    【leetcode刷题笔记】Merge k Sorted Lists
    【leetcode刷题笔记】Longest Substring Without Repeating Characters
    【leetcode刷题笔记】Scramble String
    【leetcode刷题笔记】Anagrams
    【leetcode刷题笔记】Distinct Subsequences
    【leetcode刷题笔记】Remove Duplicates from Sorted List II
    结语与感悟
  • 原文地址:https://www.cnblogs.com/hrj1/p/11139549.html
Copyright © 2011-2022 走看看