Description
杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,…VK,V1,那么必须满足K>2,就是说至除了出发点以外至少要经过2个其他不同的景区,而且不能重复经过同一个景区。现在8600需要你帮他找一条这样的路线,并且花费越少越好。
Input
第一行是2个整数N和M(N <= 100, M <= 1000),代表景区的个数和道路的条数。
接下来的M行里,每行包括3个整数a,b,c.代表a和b之间有一条通路,并且需要花费c元(c <= 100)。
Output
对于每个测试实例,如果能找到这样一条路线的话,输出花费的最小值。如果找不到的话,输出"It’s impossible.".
Sample Input
3 3
1 2 1
2 3 1
1 3 1
3 3
1 2 1
1 2 3
2 3 1
Sample Output
3
It’s impossible.
Solution
在Floyd的过程中枚举环上编号最大的点u以及与其相邻的点 i,j , 答案为
m
i
n
{
v
a
l
[
u
]
[
i
]
+
v
a
l
[
u
]
[
j
]
+
d
i
s
[
i
]
[
j
]
}
min\left\{val[u][i] + val[u][j] + dis[i][j]\right\}
min{val[u][i]+val[u][j]+dis[i][j]}
Hint
注意去掉重边
Code
const int INF = 0x3f3f3f3f;
const int maxn = 100 + 7;
int dis[maxn][maxn];
int val[maxn][maxn];
int n,m;
int main() {
while(~scanf("%d%d",&n,&m)){
for(int i = 1;i <= n;++i)
for(int j = 1;j <= n;++j){
if(i != j) dis[i][j] = val[i][j] = INF;
else dis[i][j] = val[i][j] = 0;
}
for(int i = 1,a,b,c;i <= m;++i) {
scanf("%d%d%d",&a,&b,&c);
dis[a][b] = min(dis[a][b], c);
dis[b][a] = min(dis[b][a], c);
val[a][b] = min(val[a][b], c);
val[b][a] = min(val[b][a], c);
}
if(n < 3) {printf("It's impossible.\n");continue;}
int res = INF;
for(int k = 1;k <= n;++k) {
for(int i = 1;i <= n;++i) {
for(int j = 1;j <= n;++j) {
if(i == j || i == k || j == k) continue;
if(val[k][i] != INF && val[k][j] != INF && dis[i][j] != INF) {
res = min(res, val[k][i] + val[k][j] + dis[i][j]);
}
}
}
for(int i = 1;i <= n;++i) {
for(int j = 1;j <= n;++j) {
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
}
}
if(res == INF) printf("It's impossible.\n");
else printf("%d\n", res);
}
return 0;
}