[poj1161]平面圖縮點

題目大意

In a country, great walls have been built in such a way that every great wall connects exactly two towns. The great walls do not cross each other. Thus, the country is divided into such regions that to move from one region to another, it is necessary to go through a town or cross a great wall. For any two towns A and B, there is at most one great wall with one end in A and the other in B, and further, it is possible to go from A to B by always walking in a town or along a great wall. The input format implies additional restrictions.

There is a club whose members live in the towns. In each town, there is only one member or there are no members at all. The members want to meet in one of the regions (outside of any town). The members travel riding their bicycles. They do not want to enter any towns, because of the traffic, and they want to cross as few great walls as possible, as it is a lot of trouble. To go to the meeting region, each member needs to cross a number (possibly 0) of great walls. They want to find such an optimal region that the sum of these numbers (crossing-sum, for short) is minimized.

算法思路

  1. 這是一個平面圖,我們要計算的是從多個點到一個面需要穿過多少條邊。
  2. 首先,我們將每個面縮成一個點,由於老的點可能在多個面的邊界。所以我們先要計算這一點。
  3. 其次,相鄰的面的距離爲1,其條件是有一條公共邊。一開始我先入爲主認爲就是有兩個公共頂點,結果WA了很長時間,傷心。這樣的幾何邊界可不一定是凸多邊形啊。
  4. 然後就十分簡單了,使用floyd-warshell算法計算任意兩對頂點之間的距離,然後枚舉每個面的最小叉邊數,就可以得到最後的解。

代碼

#include<iostream>
#include<cstdio>
#include<set>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;

#define MAXM 205
#define MAXL 35
#define INF 0x3f3f3f3f

int grid[MAXM][MAXM];
vector<int>People[MAXL];
int LiveIn[MAXL];
int n,m,l;
int regionNum[MAXM];
vector<int>CityList[MAXM];

bool Judge(int st,int en)
{
    int i,j;
    for(i=0;i<regionNum[st];i++){
        for(j=0;j<regionNum[en];j++){
            if(CityList[st][i] == CityList[en][j]){
                if(CityList[st][(i+1)%regionNum[st]]==CityList[en][(j-1+regionNum[en])%regionNum[en]])return true;
                else if(CityList[st][(i+1)%regionNum[st]]==CityList[en][(j+1)%regionNum[en]])return true;
                else if(CityList[st][(i-1+regionNum[st])%regionNum[st]]==CityList[en][(j-1+regionNum[en])%regionNum[en]])return true;
                else if(CityList[st][(i-1+regionNum[st])%regionNum[st]]==CityList[en][(j+1)%regionNum[en]])return true;
            }
        }
    }
    return false;
}

void get_map()
{
    int i,j,k;

    for(i=0;i<m;i++){
        for(j=i;j<m;j++){
            if(i==j)grid[i][j]=0;
            else{
                if(Judge(i,j)){
                    //printf("%d%d\n",i,j);
                    grid[i][j] = grid[j][i] = 1;
                }
                else grid[i][j] = grid[j][i] = INF;
            }
        }
    }

    for(i=0;i<l;i++){
        for(j=0;j<m;j++){
            for(k=0;k<regionNum[j];k++){
                if(CityList[j][k] == LiveIn[i]){
                    People[i].push_back(j);
                    break;
                }
            }
        }
    }
}

void Floyd()
{
    int i,j,k;

    for(i=0;i<m;i++){
        for(j=0;j<m;j++){
            for(k=0;k<m;k++){
                if(grid[j][k]>grid[j][i]+grid[i][k])
                    grid[j][k] = grid[j][i]+grid[i][k];
            }
        }
    }
}


void Solve()
{
    int ans = INF;
    int i,j,k;
    Floyd();

    /*for(i=0;i<l;i++){
        for(j=0;j<People[i].size();j++)
            printf("%d ",People[i][j]);
        printf("\n");
    }*/

    for(i=0;i<m;i++){
        int tmp=0;
        for(j=0;j<l;j++){
            int tmp2=INF;
            for(k=0;k<People[j].size();k++){
                if(grid[People[j][k]][i]<tmp2)
                    tmp2 = grid[People[j][k]][i];
            }
            tmp+=tmp2;
        }
        //printf("%d\n",tmp);
        if(tmp<ans)ans=tmp;
    }

    printf("%d\n",ans);

    return;
}


int main()
{
    freopen("WALLS4.in","r",stdin);
    int i,j,tmp;
    scanf("%d%d",&m,&n);
    scanf("%d",&l);

    for(i=0;i<l;i++)
        scanf("%d",&LiveIn[i]);

    for(i=0;i<m;i++){
        scanf("%d",&regionNum[i]);
        for(j=0;j<regionNum[i];j++){
            scanf("%d",&tmp);
            CityList[i].push_back(tmp);
        }
    }
    get_map();
    Solve();

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章