Fence Loops

题意据说是 在无向图中找一个最小环。

完全不会?~是的。

那么看网上是怎么说的。

他说的很好:

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

从网上找到了做法。。

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

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

方法一说的很有道理。但是要是TLE了就不好了。

所以我们来看简单快捷的方法二:

 

改进的Floyd:

int mincircle = infinity;
Dist = Graph;

for(int k=0;k<nVertex;++k){
    for(int i=0;i<k;++i)
        for(int j=0;j<i;++j)
             mincircle = min(mincircle,Dist[i][j]+Graph[j][k]+Graph[k][i]);//新增部分:
    for(int i=0;i<nVertex;++i)
        for(int j=0;j<i;++j){
            int temp = Dist[i][k] + Disk[k][j];
            if(temp < Dist[i][j])
                 Dist[i][j] = Dist[j][i] = temp; //通常的 floyd 部分:
         }
}

好的。看起来通俗易懂的样子。但是为什么上面那个一定要放在上面呢?

这是个好问题。顺序问题十分重要。

又有大神是这么说的:

以上为网上流传的Floyd求最小环的主代码。我们发现,最下面两重循环就是Floyd原来的代码,新增的就是上面那个判环部分。一开始,我不明白,为什么要把新增的放在前面,两者的顺序能不能调换?现在的理解是这样的:在第k层循环,我们要找的是最大结点为k的环,而此时Dist数组存放的是k-1层循环结束时的经过k-1结点的最短路径,也就是说以上求出的最短路是不经过k点的,这就刚好符合我们的要求。为什么呢?假设环中结点i,j是与k直接相连,如果先求出经过k的最短路,那么会有这样一种情况,即:ij的最短路经过k。这样的话就形成不了环,显然是错误的。当时还有一个问题,就是为什么要多开一个Dist数组呢,一个Graph不是足够了吗?其实好好想想,出现的问题和前面是一个道理。如果只开Graph,那么它里面的值就会不断改变,也会存在路径覆盖的情况,导致形成不了环或不是最小环。举个例子:假设现在进行第k层循环,i,j为枚举出来与k直接相连的边。由于此时Graph是动态的,原来根本不存在ik的一条边,现在可能经过其它结点形成了“边”,但它未必是与k直接相连的边。以上两个问题花了我半天时间来弄懂,由于网上也没有找到关于这些问题的(可能我比较笨吧),所以要写这些东西,但又写得挺乱……

他说的是有点乱。但是意思我懂了。可能算是一种偏解吧。who cares?

好的。

完整代码也没有仔细看。还是Floyd最关键,增长见识的重要性。

 

本题代码:(貌似建图很费劲的样子)

 

/*
    ID:Andy Chen
    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]);
    }
       cout<<minz<<endl;
    return 0;
}

 

posted @ 2016-02-19 21:47  A_Cherry  Views(223)  Comments(0Edit  收藏  举报