Walls POJ 1161

参考了大牛的博客 

http://blog.csdn.net/wangjian8006/article/details/7958838

题目大意:

给出n个点,在这些点中有些点是俱乐部点,并且有m个区域是由点围成的
输入第一行代表n个点
第二行代表m个区域
第3行代表俱乐部有L个
第四行有L个数,分别标记哪些个点事是俱乐部
接下来2*m行,代表m个区域,每个区域由两行表示,第一行为区域由T个点围成的,
第二行T个数代表是哪些点围成这个区域,这些点按逆时针围成这个区域,相邻两点代表一条边
最后一点和第一点也是一条边,这样就是一个闭合的区域

现在问,在图中找出一个区域,使得所有俱乐部点到这个区域所要穿过的边之和最少,
输出最少的边数之和

题目思路:

建图 假如两个区域有公共边 则 两个区域的距离是 1, 然后 Floyd 求出所有区域的距离。

剩下的暴力解解决就OK了

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
using namespace std;
#define INF 0xfffffff
#define maxn 260

struct Area
{
    int num;
    int Point[maxn];
    bool vis[maxn];
} P[maxn];

int G[maxn][maxn], Member[maxn];
int n, m, a;//n个点 m个区域 a个座城有俱乐部成员

void Floyd();
bool Adj(Area A, Area B);
int Slove();
int CountPoint(int k);

int main()
{
    cin >> m >> n >> a;

    for(int i=0; i<a; i++)
        cin >> Member[i];

    for(int i=0; i<m; i++)
    {
        cin >> P[i].num;

        for(int j=0; j<P[i].num; j++)
        {
            cin >> P[i].Point[j];
            P[i].vis[ P[i].Point[j] ] = true;
        }

        P[i].Point[P[i].num] = P[i].Point[0];
    }

    for(int i=0; i<m; i++)
    {
        for(int j=0; j<i; j++)
        {
            G[i][j] = INF;
            if( Adj(P[i], P[j]) )
                G[i][j] = 1;

            G[j][i] = G[i][j];
        }
        G[i][i] = 0;
    }

    Floyd();

    int ans = Slove();

    cout << ans << endl;

    return 0;
}
void Floyd()
{
    for(int k=0; k<m; k++)
    {
        for(int i=0; i<m; i++)
        {
            for(int j=0; j<m; j++)
            {
                if(G[i][j] > G[i][k] + G[k][j] )
                {
                    G[i][j] = G[i][k] + G[k][j];
                }
            }
        }
    }
}

bool Adj(Area A, Area B)
{
    for(int i=0; i< A.num; i++)
    {
        for(int j=0; j<B.num; j++)
        {
            if( (A.Point[i] == B.Point[j] && A.Point[i+1] == B.Point[j+1]) ||
                    (A.Point[i] == B.Point[j + 1] && A.Point[i+1] == B.Point[j]) )
                return true;
        }
    }
    return false;
}

int Slove()
{
    int index = 0, b[maxn];
    for(int i=0; i<m; i++)
    {
        b[i] = CountPoint(i);
    }

    for(int i=1; i<m; i++)
    {
        if(b[i] < b[index])
            index = i;
    }
    return b[index];
}

int CountPoint(int k)//计算所有点  到达这个区域k 需要穿越多少条边
{
    int sum = 0;

    for(int i=0; i<a; i++)
    {
        int Min = INF;
        for(int j=0; j<m; j++)
        {
            if( P[j].vis[ Member[i] ] && Min > G[j][k] )
            {
                Min = G[j][k];
            }
        }
        sum += Min;
    }
    return sum;
}
原文地址:https://www.cnblogs.com/chenchengxun/p/4174500.html