hdu1599求无向图的最小环

【题意】

       N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1,那么必须满足K>2,就是说至除了出发点以外至少要经过2个其他不同的景区,而且不能重复经过同一个景区。现在8600需要你帮他找一条这样的路线,并且花费越少越好。
【前话】
      昨晚看到队友发了篇flody算法求最小环的博文,表示flody是很久以前接触的,差不多忘了,似乎很暴力,结果我自己想了更暴力的用了单源最短路径居然给过了ranklist里垫底。下面也出来flody算法的分析,以后向chenpengyu要个100ms内的代码。
【分析】
开始看错了题,题目要求的是找最小的环,也就是不管起始点,那么:
1、枚举每个点index,
2、枚举与index相连的点ed,断开之;
3、index作为起始点,ed作为结束点,做单源最短路径,将这个结果与map[index][ed]相加后与min比较即可;
如此多重循环之后,暴力AC,具体见代码。
【代码】
/*2011-01-19 10:26:44 Accepted 1599 1562MS 276K 1632 B C++ */ 
#include<stdio.h>
#define maxn 200000000
int n,m,map[105][105];
int Dijkstra(int st,int ed){
    int i,j,dis[105];
    bool mark[105];
    for(i=1;i<=n;i++){
        mark[i]=0;
        dis[i]=map[st][i];
    }   
    mark[st]=1, dis[st]=0;
    int min,index; 
    while(1){
        min=maxn;
        for(j=1;j<=n;j++){
            if(mark[j]==0&&dis[j]<min)
                min=dis[j], index=j;
        }    
        if(min==maxn) break;
        mark[index]=1; //必须放在上面的判断语句的后面,否则运行报错;
        for(j=1;j<n;j++){
            if(mark[j]==0&&map[index][j]+min<dis[j])
                    dis[j]= map[index][j]+min;
        }
    }
    return dis[ed];          
}
int main()
{
    int i,j,a,b,c;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(i=1;i<=n;i++) for(j=1;j<=n;j++) map[i][j]=maxn;
        for(i=1;i<=m;i++){
            scanf("%d%d%d",&a,&b,&c);
            if(c<map[a][b]||c<map[b][a]) map[a][b]=c,map[b][a]=c;
        }
        int min=maxn,res,tmp;
        for(j=1;j<=n;j++){ //每个点都要这样做一遍;
            for(i=1;i<=n;i++){
                if(map[j][i]<maxn){//与1连通,断开之,求单源最短路径;
                    tmp=map[j][i];
                    map[i][j]=map[j][i]=maxn;
                    res= Dijkstra(j,i);
                    if(res+tmp<min) min=res+tmp;
                    map[i][j]=map[j][i]=tmp;
                }
            }       
        }
        if(min==maxn) printf("It's impossible./n");
        else printf("%d/n",min);
    }       
}       
另外用Flody算法做可参考这个博文,写的N好:
chenpengyu的100ms内的代码拿到手后再去研究。。。话说pku1723也是最小环的,赶紧去刷。
之后看下Floyd算法写发现是78ms,快多了,注意Floyd算法改进后的代码的思想及与此题的联系,详细见下面的代码及说明;
【Floyd算法写的代码】
/*2011-01-19 14:00:11 Accepted 1599 78MS 324K 1273 B C++*/
#include<stdio.h>
#define maxn 21000000
#define arr 105
int n,m,dis[arr][arr];//dis[][]保存可以达到的最短距离,会变化;
int g[arr][arr];//g[][]保存图的信息,不做变化;


void Floyd(){
    int i,j,k,ans=maxn;
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            dis[i][j]=g[i][j];//初始化两点之间的最短距离;
    for(k=1;k<=n;k++){
        for(i=1;i<=k;i++){
            for(j=1;j<i;j++){
                if(dis[i][j]+g[i][k]+g[k][j]<ans)
                    ans= dis[i][j]+g[i][k]+g[k][j];
            }
        }//可以保证环最少包含3个点,因为是三重循环,且g[i][i]=maxn;
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++){
                if(dis[i][j]>dis[i][k]+dis[k][j])       
                    dis[i][j]=dis[i][k]+dis[k][j];
            }//不断更新两点之间的最短距离;
     }
     if(ans==maxn) printf("It's impossible./n");
     else printf("%d/n",ans);      
}   

int main()
{
     int i,j,c;
     while(scanf("%d%d",&n,&m)!=EOF)
     {
         for(i=1;i<=n;i++)for(j=1;j<=n;j++)g[i][j]=maxn;
         while(m--){
             scanf("%d%d%d",&i,&j,&c);
             if(c<g[i][j]) g[i][j]=g[j][i]=c;
         }
         Floyd();
     }
 }           

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值