hdu 4606 Occupy Cities(线段相交+最小路径覆盖+二分)

Occupy Cities

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1178    Accepted Submission(s): 388

Problem Description

The Star Wars is coming to an end as the Apple Planet is beaten by the Banana Planet. Captain Chen, the glorious leader of the Army of Banana Planet, has drawn up a plan to occupy all the cities on the Apple Planet. The Army of Banana Planet totally has P soldiers,
and thus, Captain Chen can only conduct at most P soldiers to occupy the cities.

The cities on the planet can be regarded as points on a 2D plane. What‘s more, there are some barriers on the planet, which can be seen as segments on the plane. When a soldier moves from city to city, he‘s not allowed to cross or touch the barriers. However,
the soldiers are smart enough to go along the shortest paths between cities.

But these soldiers are just soldiers, whereupon they also need food to replenish their energy. A soldier needs one unit of food to move one unit of distance forward. Fortunately, all the cities have sufficient food supplies. When a soldier steps in a city,
he will fill up his food bag. Invaders as they are, the soldiers will burn up all the food after filling his bag. And thus, each city can supply only one soldier.

When a soldier steps in a city, this city is occupied by the Army of Banana Planet immediately. Soldiers can also just pass by a city but not step in. In this case, this city is not occupied yet, and the food in the city would not be burned.

Captain Chen has an occupying schedule for his soldiers. If city A is arranged before city B on the schedule, city A must be occupied before city B. All the soldiers will strictly follow this schedule. During the occupying process, soldiers can be air-dropped
to any positions on the plane as needed. After a soldier lands on the ground, he can only move on foot, and replenish his energy by the food in his bag. Note that their bags are full of food initially, and all bags have the same volume for soldiers.

You, the logistics minister of the army, are required to help the Captain to cut down the cost and determine the minimal volume of all P soldiers‘ food bags to finish occupying. All the requirements above should be fulfilled for sure.

Input

The first line contains an integer T(T≤50), indictaing the number of test cases.

Each test case begins with three integers n(0<n≤100), m(0≤m≤100) and p(0<p≤100), which respectively denotes the number of cities, barriers and soldiers.

The following n lines describe the cities‘ coordinates (x_i,y_i).

The next m lines, each with two pairs of integers (sxi,syi) and (exi,eyi), describe the two endpoints of each barrier.

The last line of each test case consists of n integers, describing the occupying schedule in order.

All the coordinates range from -10000 to 10000, and cities are labeled from 1 to n. You may assume that any two barriers will not have common points and cities will not be built on barriers.

Output

For each test case, output the minimal volume of soldiers‘ food bag, in accuracy of two decimal places. The answers should be printed one per line.

Sample Input

2

2 1 1
0 0
2 0
1 1 1 -1
2 1

4 2 2
0 1
5 1
8 0
1 -1
0 0 2 0
6 0 6 3
1 2 3 4

Sample Output

2.83
3.41

Hint

For the second sample case, the best strategy is:
step 1: air-drop soldier 1 to city 1, city 1 occupied;
step 2: air-drop soldier 2 to city 2, city 2 occupied;
step 3: soldier 2 moves from city 2 to city 3, city 3 occupied, and 3.41 units of food needed;
step 4: soldier 1 moves from city 1 to city 4, city 4 occupied, and 2.41 units food needed.
Therefore, the minimal volume of bags is 3.41.

题意:有n个城市,然后有p个士兵要去占领,路上有m个路障,都是线段,士兵

不能越过路障前进。每个士兵都有相同容量大小的一个干粮袋,每到一个城市他

就能补充满自己的干粮袋。中途走路时走一个单位长度就消耗一个单位的干粮。

现在问的是这些个干粮袋最小的容量是多少,前提是保证p个士兵能占领完这n个

城市,城市被占领顺序也是题目给好的,必须遵守。

思路:P个士兵占领n个城市,可以看成p个士兵走出了p个路径,覆盖了所有的点。

最小路径覆盖的要求之一就是有向,无环,在题目中的体现就是城市被占领时必须

有顺序。然后枚举所有顶点,求一下距离,判断是否与线段相交。然后 floyd预处

理最短路,之后是二分答案,判断是否可达根据占领的先后顺序建边,根据二分

的值判断不需要补给是否能够到达。判断条件为最小路径覆盖数是否小于等于P。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const double eps=1e-7;
const double inf=999999999;
const int maxn=310;

struct point
{
    double x,y;
    point() {}
    point(double _x,double _y):x(_x),y(_y) {}
    friend point operator - (const point &p,const point &q)
    {
        return point(p.x-q.x,p.y-q.y);
    }
    friend bool operator == (const point &p,const point &q)
    {
        if(fabs(p.x-q.x)<eps && fabs(p.y-q.y)<eps) return true;
        return false;
    }
} A[maxn],B[maxn],C[maxn];

int n,m,p,cnt,a[maxn],match[maxn];
double dis[maxn][maxn];
bool con[maxn][maxn],visited[maxn];

double dcheng(point p,point q)
{
    return (p.x*q.y-p.y*q.x);
}

bool cross(point x1,point y1,point x2,point y2)
{
    double t1=dcheng(y1-x1,x2-x1);
    double t2=dcheng(y1-x1,y2-x1);
    double t3=dcheng(y2-x2,x1-x2);
    double t4=dcheng(y2-x2,y1-x2);
    if(t1*t2<0 && t3*t4<0)  return true;
    return false;
}

double dist(point p,point q)
{
    return sqrt((p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y));
}

void initial()
{
    for(int i=0; i<maxn; i++)
        for(int j=0; j<maxn; j++)
           {
               if(i==j)  dis[i][j]=0;
               else  dis[i][j]=inf;
           }
}

void input()
{
    scanf("%d %d %d",&n,&m,&p);
    cnt=n;
    for(int i=1; i<=n; i++)   scanf("%lf %lf",&A[i].x,&A[i].y);
    for(int i=0; i<m; i++)
    {
        scanf("%lf %lf %lf %lf",&B[i].x,&B[i].y,&C[i].x,&C[i].y);
        A[++cnt]=B[i];
        A[++cnt]=C[i];
    }
    for(int i=0; i<n; i++)    scanf("%d",&a[i]);
}

void ready()
{
    for(int i=1; i<=cnt; i++)
        for(int j=i+1; j<=cnt; j++)
        {
            bool flag=1;
            for(int k=0; k<m; k++)
            {
                if((A[i]==B[k] && A[j]==C[k]) || (A[i]==C[k] && A[j]==B[k])) continue;
                if(cross(A[i],A[j],B[k],C[k]))
                {
                    flag=0;
                    break;
                }
            }
            if(flag)  dis[i][j]=dis[j][i]=dist(A[i],A[j]);
        }

}

void floyd()
{
    for(int k=1;k<=cnt;k++)
        for(int i=1;i<=cnt;i++)
           for(int j=1;j<=cnt;j++)
               dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}

void build(double r)
{
    memset(con,0,sizeof(con));
    memset(match,-1,sizeof(match));
    for(int i=0;i<n;i++)
        for(int j=i+1;j<n;j++)
         {
              double t=dis[a[i]][a[j]];
              if(t<r || fabs(t-r)<eps)  con[a[i]][a[j]]=1;
         }
}

bool dfs(int x)
{
    for(int i=1;i<=n;i++)
    {
        if(con[x][i] && !visited[i])
        {
            visited[i]=1;
            if(dfs(match[i]) || match[i]==-1)
            {
                 match[i]=x;
                 return true;
            }
        }
    }
    return false;
}

bool judge()
{
    int ret=0;
    for(int i=1;i<=n;i++)
    {
        memset(visited,0,sizeof(visited));
        if(dfs(i))  ret++;
    }
    if(n-ret<=p)  return true;
    return false;
}

void solve()
{
    floyd();
    double l=0.0,r=inf;
    while(l+eps<r)
    {
        double mid=(l+r)/2;
        build(mid);
        if(judge()) r=mid;
        else l=mid;
    }
    printf("%.2lf\n",r);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        initial();
        input();
        ready();
        solve();
    }
    return 0;
}
时间: 2024-10-11 18:18:18

hdu 4606 Occupy Cities(线段相交+最小路径覆盖+二分)的相关文章

HDU 3861 The King’s Problem 最小路径覆盖(强连通分量缩点+二分图最大匹配)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3861 最小路径覆盖的一篇博客:https://blog.csdn.net/qq_39627843/article/details/82012572 题意: 把城市至少分成几个块,规则有三 1. A能B,B能到A,那么A,B一定要在一起. 2. 一个城市只能属于一个块. (说明了是最小不相交覆盖)3. 在一个块里的城市,任意2点之间必须有路径. 对于规则1,就是说强连通的必须在一起,所以用Tarjan

poj 2594 Treasure Exploration(最小路径覆盖/二分最大匹配)

Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 7208   Accepted: 2944 Description Have you ever read any book about treasure exploration? Have you ever see any film about treasure exploration? Have you ever explored

hdu 3861 The King’s Problem (强连通+最小路径覆盖)

The King's Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1637    Accepted Submission(s): 600 Problem Description In the Kingdom of Silence, the king has a new problem. There are N cit

HDU 3861.The King’s Problem 强联通分量+最小路径覆盖

The King’s Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 2947    Accepted Submission(s): 1049 Problem Description In the Kingdom of Silence, the king has a new problem. There are N cit

HDU 1151 Air Raid(最小路径覆盖 = 顶点数 - 最大匹配数)

Air Raid Problem Description Consider a town where all the streets are one-way and each street leads from one intersection to another. It is also known that starting from an intersection and walking through town's streets you can never reach the same

HDU 4160 最小路径覆盖

Dolls Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1040    Accepted Submission(s): 496 Problem Description Do you remember the box of Matryoshka dolls last week? Adam just got another box of

HDU 3861 The King’s Problem(强连通+二分图最小路径覆盖)

HDU 3861 The King's Problem 题目链接 题意:给定一个有向图,求最少划分成几个部分满足下面条件 互相可达的点必须分到一个集合 一个对点(u, v)必须至少有u可达v或者v可达u 一个点只能分到一个集合 思路:先强连通缩点,然后二分图匹配求最小路径覆盖 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #include <

HDU 1350 最小路径覆盖

Taxi Cab Scheme Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 707    Accepted Submission(s): 336 Problem Description Running a taxi station is not all that simple. Apart from the obvious dem

hdu 1151 Air Raid (最小路径覆盖)

Air Raid Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3085    Accepted Submission(s): 2004 Problem Description Consider a town where all the streets are one-way and each street leads from on