无向图最小环

【题目描述】:

给定一张无向图,求图中一个至少包含 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\n",ans[i]);
        }
    }
    return 0;
}

 

posted @ 2019-07-05 17:15  魂兮龙游  阅读(287)  评论(0)    收藏  举报