“路痴“ST
时间限制:
2000 ms | 内存限制:
65535 KB
难度:
3
-
描述
-
当大一新生ST刚到新的学校的时候对自己的大学校园充满了好奇。但是ST是一个典型的路痴,所以每次出去之后都要想好回到原处的路线(即,从某点A出发,最终将回到A)。现在ST很想好好的参观一下美丽的校园,且ST开始的时候从某处出发选择的路都是双向的。假设经过的路线为V1,V2,....VK,V1,那么必须满足K>2,就是说除了出发点以外至少要经过2个其他不同的校园建筑,而且不能重复经过同一个建筑物。现在ST需要你帮他找一条这样的路线,并且所花费的时间越少越好。
-
输入
-
第一行是2个整数N和M(N <= 100, M <= 1000),代表建筑物的个数和道路的条数。
接下来的M行里,每行包括3个整数a,b,c.代表a和b之间有一条通路,并且需要时间花费c分钟(c <= 100)。
输出
- 对于每个测试实例,如果能找到这样一条路线的话,输出花费的时间的最小值。如果找不到的话,输出"It's impossible." 样例输入
-
3 31 2 12 3 11 3 13 31 2 11 2 32 3 1
样例输出
-
3It's impossible.
-
第一行是2个整数N和M(N <= 100, M <= 1000),代表建筑物的个数和道路的条数。
首先,对于两点之间有重边的情况只考虑权值最小的情况。
接下来,建立最小生成树:
在建立最小生成树的时候要注意记录边是否在树上:
看到这里就应该有几分懂了吧。因为生成了树,树上任意两点连边都会形成环,这就是可以出去再回来的路。这时候我又用了warshall计算了树上的两点间最短路。
最后枚举所有不在树上的边,值因为两点间的树上最短路+所枚举的边权,记录最小值。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
#define Maxsize 110
#define INF 0x3f3f3f3f
int n,m;
int dist[Maxsize];
int g[Maxsize][Maxsize];
int mincost[Maxsize][Maxsize];
int pre[Maxsize];
bool used[Maxsize][Maxsize];
bool vis[Maxsize];
void init()
{
memset(g,0x3f,sizeof(g));
memset(dist,0x3f,sizeof(dist));
memset(mincost,0x3f,sizeof(mincost));
memset(used,0,sizeof(used));
memset(vis,0,sizeof(vis));
for(int i=0;i<=n;i++)
mincost[i][i]=0;
}
void addedge(int a,int b,int c)
{
if(c<g[a][b])
{
g[a][b]=c;
g[b][a]=c;
}
}
int findmin(int x,int y)
{
return x>y?y:x;
}
void findtree()
{
int u;
dist[1]=0;
pre[1]=0;
for(;;)
{
int min=INF;
for(int i=1;i<=n;++i)
if(min>dist[i]&&!vis[i])
{
min=dist[i];
u=i;
}
if(min==INF)
break;
vis[u]=1;
int v=pre[u];
used[u][v]=used[v][u]=1;
mincost[u][v]=mincost[v][u]=g[u][v];
for(v=1;v<=n;v++)
if(!vis[v]&&dist[v]>g[u][v])
{
pre[v]=u;
dist[v]=g[u][v];
}
}
/*for(int p=1;p<=n;p++)
{
for(int q=1;q<=n;q++)
printf("%d ",used[p][q]);
printf("\n");
}*/
}
void findmincostload()
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
mincost[i][j]=findmin(mincost[i][j],mincost[i][k]+mincost[k][j]);
/*for(int p=1;p<=n;p++)
{
for(int q=1;q<=n;q++)
printf("%d ",mincost[p][q]);
printf("\n");
}*/
}
int solve()
{
int res=INF;
findtree();
findmincostload();
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(used[i][j]==0)
res=findmin(res,mincost[i][j]+g[i][j]);
return res;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
int a,b,c;
for(int i=0;i<m;++i)
{
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);
}
int t=solve();
if(t==INF)
printf("It's impossible.\n");
else printf("%d\n",t);
}
return 0;
}