BSOJ3138【SPFA】火炬传递(刘峻琳day2-2)

Description

2012伦敦奥运会就要来了,此次伦敦奥运的火炬将不再进行全球传递,也就是只在本国英国传递。伦敦奥组委计划将火炬传遍英国的各个角落,这下可苦了某些城市的市长,由于欧债危机,他们实在无钱支付火炬传递需要的开销。于是设计一条花费最小的火炬传递路线势在必行。X市的格局很神奇,这个市是一个类似威尼斯的水城,共有n个岛,并且有m条桥连接着它们,这些桥在火炬传递期间只能单向行进,通过每座桥都有一定的费用(包括环境布置等)。火炬传递的路线必须是一个环,也就是说,你可以任意选择一个岛出发,最后必须回到这个岛。现在请你找出花费最小的一条火炬传递路线。

Input

输入第一行包含两个整数n,m,表示岛屿个数和桥的个数。 
接下来m行,第i行两个整数,x,y, c,表示可以从岛x经过第i座桥到达岛y,花费为c。

Output

输出一行,最小花费。

Sample Input

10 15
8 9 1
6 2 10
2 4 5
3 1 5
1 4 3
6 7 10
2 9 9
1 5 8
10 6 5
3 10 4
8 6 8
6 5 4
6 4 8
3 2 9
7 8 5

Sample Output

23

Hint

对于50%的数据n<=200, m<=2000 
对于100%的数据n<=1000, m<=10000

Source

刘峻琳(详情请看:360百科

分析

用n遍前向星SPFA实现求出任意2点之间的最短路,然后枚举求答案。

PS:read()玄学啊啊啊!!!!!千万不要用addedge(read(),read(),read())!!!!!答案是错的啊啊啊啊啊!!!我找了半个小时错误啊!!!

//题解by disangan233 or Lixiuyu 
#include<bits/stdc++.h>
using namespace std;
#define re register long long
#define ll long long
ll cnt,n,m,h[20005],dis[1005][1005],vis[1005],ans=1234567890;
struct did{
	ll next,to,l; 
}e[20005]; 
queue<ll>q;//spfa 
inline ll read()
{
	char did=getchar();
	re luoyang=0,yz=1;
	while(!isdigit(did)){if(did=='-')yz=-1;did=getchar();}
	while(isdigit(did))luoyang=luoyang*10+did-'0',did=getchar();
	return yz*luoyang; 
}
inline void add(ll x,ll y,ll z)//前向星 
{
	e[++cnt].to=y;
	e[cnt].l=z;
	e[cnt].next=h[x];
	h[x]=cnt;
}
inline void spfa(ll s)//spfa
{
    memset(vis,0,sizeof(vis));
    ll g,j;    
    for(re t=1;t<=n;++t)  
    dis[s][t]=13145201314;  
    dis[s][s]=0;  
    while(!q.empty()) q.pop();  
    q.push(s);  
    vis[s]=1;  
    while(!q.empty())  
    {  
        g=q.front();  
        q.pop();  
        vis[g]=0;  
        for(j=h[g];j;j=e[j].next)  
        {  
            if(dis[s][e[j].to]>e[j].l+dis[s][g])  
            {  
                dis[s][e[j].to]=e[j].l+dis[s][g];  
                if(!vis[e[j].to])       
               	{  
                    vis[e[j].to]=1;  
                    q.push(e[j].to);  
                }  
            }  
        }  
    }  
}
int main()
{
	n=read();m=read();
	for(re i=1;i<=m;i++)
	{
		re x=read(),y=read(),z=read();add(x,y,z);
//		add(read(),read(),read());不要用这个!!!!!!!!!!!!!!!!!!!!!!! 
	}//有向边 
	for(re i=1;i<=n;i++)
	spfa(i);
	for(re i=1;i<=n;i++)
	for(re j=1;j<=n;j++)
	if(i!=j)
        ans=min(ans,dis[i][j]+dis[j][i]);
	cout<<ans<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/disangan233/article/details/80951473