您的位置:首页 > Web前端

USACO 4.1 Fence Loops(无向图中的最小环)

2013-02-20 17:16 274 查看
这个算是一个模版题,不过以前没见过。。。我冥思苦想,想爆搜,却知从何搜起,然后突然想到以前做过一个最小环的,关于某一个点的最小环两遍spfa,搞定。然后我啪啪开写,先自己把数据转化为点,然后离散一下。。。写了老长,还选择比较好写的floyd,样例过不了,意识到发现这样写不对啊。。。

从网上找到了做法。。

1:朴素的求最小环的方法做E遍Dijkstra,枚举每条边e(i,j),删去边e(i,j)之后,求i到j的最短路经,然后再加上该边求最小值便得到的了最小环,时间复杂度为O(E*(N^2))。

2:改进的floyd算法,求出任意两点之间的最短路的同时,求出最小环。

我用的是后者,因为图都建好了。。。不能白写了啊。。。证明详细,还是去搜网上的资料把。

/*
ID: cuizhe
LANG: C++
TASK: fence6
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <string>
#include <vector>
using namespace std;
#define N 10000000
int o[301];
int dp[201][201],g[201][201];
struct point
{
int x,y,dis;
int nl,nr;
int L[9],R[9];
} p[101];
int pfind(int x,int key)
{
int i;
for(i = 1; i <= p[key].nl; i ++)
{
if(p[key].L[i] == x)
return p[key].x;
}
for(i = 1; i <= p[key].nr; i ++)
{
if(p[key].R[i] == x)
return p[key].y;
}
return 200;
}
int  build(int n)//建图
{
int i,j,r,c,num;
for(i = 1; i <= n; i ++)
{
o[p[i].x] = 1;
o[p[i].y] = 1;
}
num = 1;
for(i = 1; i <= 2*n; i ++)
{
if(o[i])
o[i] = num ++;
}
for(i = 1; i <= num-1; i ++)
{
for(j = 1; j <= num-1; j ++)
{
g[i][j] = dp[i][j] = N;
}
g[i][j] = dp[i][i] = 0;
}
for(i = 1; i <= n; i ++)
{
if(o[p[i].x] > o[p[i].y])
{
r = o[p[i].x];
c = o[p[i].y];
}
else
{
c = o[p[i].x];
r = o[p[i].y];
}
g[r][c] = dp[r][c] = min(dp[r][c],p[i].dis);
g[c][r] = dp[c][r] = min(dp[c][r],p[i].dis);
}
return num-1;
}
int main()
{
int i,j,n,num,k,minz;
freopen("fence6.in","r",stdin);
freopen("fence6.out","w",stdout);
scanf("%d",&n);
for(i = 1; i <= n; i ++)
{
p[i].x = 2*i-1;
p[i].y = 2*i;
}
for(i = 1; i <= n; i ++)
{
scanf("%d",&num);
scanf("%d%d%d",&p[num].dis,&p[num].nl,&p[num].nr);
for(j = 1; j <= p[num].nl; j ++)
scanf("%d",&p[num].L[j]);
for(j = 1; j <= p[num].nr; j ++)
scanf("%d",&p[num].R[j]);
}
for(i = 1; i <= n; i ++)
{
for(j = 1; j <= p[i].nl; j ++)
{
p[i].x = min(p[i].x,pfind(i,p[i].L[j]));
}
for(j = 1; j <= p[num].nr; j ++)
{
p[i].y = min(p[i].y,pfind(i,p[i].R[j]));
}
}
n = build(n);
minz = N;
for(i = 1; i <= n; i ++)//求最小环
{
for(j = 1; j <= i-1; j ++)
for(k = j+1; k <= i-1; k ++)
minz = min(minz,dp[j][k] + g[j][i] + g[i][k]);
for(j = 1; j <= n; j ++)
for(k = 1; k <= n; k ++)
dp[j][k] = min(dp[j][k],dp[j][i]+dp[i][k]);
}
printf("%d\n",minz);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: