题目
n(n<=100)个点,m(m<=1e3)条双向边,第i条边代价c(c<=100)元,
从V1出发,假设经过的路线为V1,V2,....VK,V1,那么必须满足K>2,
即除了出发点以外至少要经过2个其他不同的景区,而且不能重复经过同一个景区。
现在8600需要你帮他找一条这样的路线,并且花费越少越好。
能找到输出最小代价,不能找到输出It's impossible.
思路来源
https://www.cnblogs.com/mt522/p/5404165.html
题解
dp[i][j]是floyd上最小代价,而mp[i][j]是原边,考虑更新第k个点时,1到k-1的点已被更新
则不妨认为起点k,通过枚举途中必经的两个点i,j,
通过k直接到i,i到j的最小代价,j直接到k,来更新答案
i和j保证了这条路径上至少两个点,k还没更新保证了i到j的最小代价里不会经过k
心得
fzu2090统计最小代价的环的个数,这里就很简单了,
魔改一下,更新ans的部分即可
代码
#include<bits/stdc++.h>
using namespace std;
const int N=105,INF=1e7;
int n,m,u,v,w,dp[N][N],mp[N][N];
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;++i)
{
for(int j=i+1;j<=n;++j)
{
mp[i][j]=mp[j][i]=INF;
dp[i][j]=dp[j][i]=mp[i][j];
}
}
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&u,&v,&w);
mp[u][v]=mp[v][u]=min(mp[u][v],w);
dp[u][v]=dp[v][u]=mp[u][v];
}
int ans=INF;
for(int k=1;k<=n;++k)
{
for(int i=1;i<k;++i)
{
for(int j=i+1;j<k;++j)
{
ans=min(ans,mp[k][i]+dp[i][j]+mp[j][k]);
}
}
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
}
}
}
if(ans==INF)puts("It's impossible.");
else printf("%d\n",ans);
}
return 0;
}