-->

POJ 1161 Walls(最短路+枚举)

POJ 1161 Walls(最短路+枚举)

题目背景

题目大意:题意是说有 n个小镇,他们两两之间可能存在一些墙(不是每两个都有),把整个二维平面分成多个区域,当然这些区域都是一些封闭的多边形(除了最外面的一个),现在,如果某几个小镇上的人想要聚会,为选择哪个区域为聚会地点,可以使他们所有人总共需要穿过的墙数最小,题目上有说明,不在某个点上聚会(聚会点在某个多边形内部),行进过程中不穿过图中的点(也就是除出发点外的其他小镇)。

输入第1行代表m(2<=M<=200)个区域

第2行代表n(3<=N<=250)个点

第3行代表俱乐部有L(1<=L<=30&&L<=N)个

第四行有L个数,分别标记哪些个点事是俱乐部

接下来2*m行,代表m个区域,每个区域由两行表示,第一行为区域由T个点围成的,

第二行T个数代表是哪些点围成这个区域,这些点按逆时针围成这个区域,相邻两点代表一条边

最后一点和第一点也是一条边,这样就是一个闭合的区域

输出最少的边数之和

题目描述

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.

The towns are labeled with integers from 1 to N, where N is the number of towns. In Figure 1, the labeled nodes represent the towns and the lines connecting the nodes represent the great walls. Suppose that there are three members, who live in towns 3, 6, and 9. Then, an optimal meeting region and respective routes for members are shown in Figure 2. The crossing-sum is 2: the member from town 9 has to cross the great wall between towns 2 and 4, and the member from town 6 has to cross the great wall between towns 4 and 7.

You are to write a program which, given the towns, the regions, and the club member home towns, computes the optimal region(s) and the minimal crossing-sum.

输入输出格式

输入格式:

Your program is to read from standard input. The first line contains one integer: the number of regions M, 2 <= M <= 200. The second line contains one integer: the number of towns N, 3 <= N <= 250. The third line contains one integer: the number of club members L, 1 <= L <= 30, L <= N. The fourth line contains L distinct integers in increasing order: the labels of the towns where the members live.

After that the input contains 2M lines so that there is a pair of lines for each region: the first two of the 2M lines describe the first region, the following two the second and so on. Of the pair, the first line shows the number of towns I on the border of that region. The second line of the pair contains I integers: the labels of these I towns in some order in which they can be passed when making a trip clockwise along the border of the region, with the following exception. The last region is the "outside region" surrounding all towns and other regions, and for it the order of the labels…

输出格式:

Your program is to write to standard output. The first line contains one integer: the minimal crossing-sum.

Sample Input

输入输出样例

输入样例#1

10
10
3
3 6 9 
3
1 2 3 
3
1 3 7 
4
2 4 7 3 
3
4 6 7 
3
4 8 6 
3
6 8 7 
3
4 5 8 
4
7 8 10 9 
3
5 10 8 
7
7 9 10 5 4 2 1

 

解题报告

这个题目比较奇葩。题意是让求穿过边的数量最小,所以我们可以把一个区域变成一个点,把公共边做成一条路。我们枚举每一个区域作为起点,用堆优dijkstra来求到每个区域的距离。因为题目问的是点到区域的距离,所以我们在计算总距离时,对于每个点我们要枚举其所属的区域,取最小值作为距离累加进答案。最后,再在每个由区域作为起点的答案中取最小值。 对于判断两个区域是否相邻,我的方法比较蠢,就是判断区域有没有公共边。如果数据卡人估计我也过不了。=,=!

 

#include <stdio.h>
#include <queue>
#include <cmath>
#include <string.h>
#include <iostream>
#include <algorithm>
#define Pair pair<int,int>
#define MAXN 600+10
#define MAXM 1200000+1
using namespace std;
int l,n,m,num,head[MAXN],t,dis[MAXN][MAXN],v[MAXM];
int ans[MAXN],minn=999999999,mian[MAXN][MAXN],pre[MAXN];
int map[MAXN][MAXN];
struct {
    int p[MAXN];
    void e()
    {
        memset(p,0,sizeof(p));
    }
}po[MAXN];

struct Edge{
    int dis,next,to,exi,from;
}edge[MAXM];


void add(int from,int to,int dis)
{
    edge[++num].next=head[from];
    edge[num].to=to;
    edge[num].dis=dis;
    edge[num].from=from;
    head[from]=num;
}


void dij(int s)
{
    memset(v,0,sizeof(v));
    priority_queue<Pair,vector<Pair>,greater<Pair> > h;
    for(int i=1;i<=m;i++) dis[s][i]=999999999;
    dis[s][s]=0;
    h.push(Pair(dis[s][s],s));
    while(h.size()>0)
    {
        int k=h.top().second;h.pop();
        if(v[k]) continue;
        v[k]=1;
        for(int i=head[k];i;i=edge[i].next)
        if(dis[s][k]+edge[i].dis<dis[s][edge[i].to])
        {
            dis[s][edge[i].to]=dis[s][k]+edge[i].dis;
            h.push(Pair(dis[s][edge[i].to],edge[i].to));
            if(s==1) pre[edge[i].to]=edge[i].from;
        }
    }
}

int main()
{


    scanf("%d%d%d",&m,&n,&l);
    int numm=0;
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        map[i][j]=map[j][i]=(++numm);
    for(int i=1;i<=l;i++)
        scanf("%d",&ans[i]);
    sort(ans+1,ans+l+1);
    for(int i=1;i<=m;i++)
    {
        int t=0,f=0,tt[MAXN];memset(tt,0,sizeof(tt));
        scanf("%d",&t);po[i].p[0]=t;
        for(int j=1;j<=t;j++)
        {
            scanf("%d",&f);tt[j]=f;mian[f][++mian[f][0]]=i;
            if(j>1)
            {
             po[i].p[j-1]=map[tt[j]][tt[j-1]];
            }
            
        }
        po[i].p[t]=map[tt[1]][tt[t]];
    }
    for(int i=1;i<=m;i++)
    {
        for(int j=i+1;j<=m;j++)
        {
            int flag=0;
            for(int a1=1;flag==0&&a1<=po[i].p[0];a1++)
                for(int a2=1;flag==0&&a2<=po[j].p[0];a2++)
                {
                    if(po[i].p[a1]==po[j].p[a2])
                    {add(i,j,1);add(j,i,1);flag=1;break;}
                }
            
        }
    }
    
    for(int i=1;i<=m;i++)
        dij(i);
    for(int i=1;i<=m;i++)
    {
        int temp=0;
        for(int j=1;j<=l;j++)
        {
            int dc=99999999;
            for(int d=1;d<=mian[ans[j]][0];d++)
            {
                dc=min(dc,dis[i][mian[ans[j]][d]]);
            }
            temp+=dc;
        }
        minn=min(minn,temp);
    }
    printf("%d\n",minn);

    return 0;
}

 

posted @ 2017-01-24 10:06  yangyaojia  阅读(458)  评论(0编辑  收藏  举报