您的位置:首页 > 其它

ural 1004 Sightseeing Trip

2013-04-06 22:27 357 查看
题意:给一个无环边可以有重边的无向带权图,求最小环的顶点序列

思路1:对每一条边 e = (v, w) 而言,在原图中删去这条边e,再做从v到w的最短路,|e| + dijkstra(v,w) 就是这个环的的长度,复杂度是O(e*O(dijkstra))

思路2:用floyd求最小环,复杂度O(n^3),不过记录顶点序列的时候很尴尬啊- -...

#include <cstdio>
using namespace std;
#define N 105
#define INF 1000000
int g

, n;
int dist
, route
;
int ans
, ast, aed, an;
bool vis
;
void input()
{
for (int i = 1; i <= n; ++ i)
for (int j = 1; j <= n; ++ j)
g[i][j] = INF;
ast = aed = an = 0;
int m, st, ed, wgt;
scanf("%d", &m);
while (m --)
{
scanf("%d%d%d",&st,&ed,&wgt);
if (g[st][ed] > wgt) g[st][ed] = g[ed][st] = wgt;
}
}
void getNewRoute(int st, int ed)
{
an = 0;
while (ed != st)
{
ans[an++] = ed;
ed = route[ed];
}
ans[an++] = ed;
}
int dijkstra(int st, int ed)
{
for (int i = 1; i <= n; ++ i)
{
vis[i] = false;
dist[i] = INF;
}
dist[st] = 0;
int node, mind;
while (true)
{
node = -1;
mind = INF;
for (int i = 1; i <= n; ++ i)
{
if (!vis[i] && dist[i] < mind)
{
node = i;
mind = dist[i];
}
}
if (node == ed) return mind;
if (node == -1) break;
vis[node] = true;
for (int j = 1; j <= n; ++ j)
{
if (g[node][j]!=INF && !vis[j] && mind+g[node][j]<dist[j])
{
dist[j] = mind+g[node][j];
route[j] = node;
}
}
}
return INF;
}
void solve()
{
int mincircle = INF, dijk;
for (int i = 1; i <= n; ++ i)
{
for (int j = 1; j < i; ++ j)
{
if (g[i][j] != INF)
{
int tedge = g[i][j];
g[i][j] = g[j][i] = INF;
dijk = dijkstra(i,j);
if (dijk + tedge < mincircle)
{
mincircle = dijk + tedge;
ast = i;
aed = j;
getNewRoute(ast,aed);
}
g[i][j] = g[j][i] = tedge;
}
}
}
}
void output()
{
if (an != 0)
{
for (int i = 0; i < an-1; ++ i)
printf("%d ", ans[i]);
printf("%d\n", ans[an-1]);
}
else printf("No solution.\n");
}
int main()
{
while (true)
{
scanf("%d", &n);
if (n == -1) break;
input();
solve();
output();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: