hdoj 4183 Pahom on Water 【网络流 简单题】【dinic求最大流】

本文介绍了一个基于Leo Tolstoy故事的游戏PahomonWater,玩家需引导角色穿越一系列彩色光谱垫,从红色到达紫色再返回。文章提供了一种解决方案,通过构建图模型并运用最大流算法来判断是否存在有效的路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Pahom on Water

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 653    Accepted Submission(s): 299


Problem Description
Pahom on Water is an interactive computer game inspired by a short story of Leo Tolstoy about a poor man who, in his lust for land, forfeits everything. The game's starting screen displays a number of circular pads painted with colours from the visible light spectrum. More than one pad may be painted with the same colour (defined by a certain frequency) except for the two colours red and violet. The display contains only one red pad (the lowest frequency of 400 THz) and one violet pad (the highest frequency of 789 THz). A pad may intersect, or even contain another pad with a different colour but never merely touch its boundary. The display also shows a figure representing Pahom standing on the red pad.
The game's objective is to walk the figure of Pahom from the red pad to the violet pad and return back to the red pad. The walk must observe the following rules:
1.If pad α and pad β have a common intersection and the frequency of the colour of pad α is strictly smaller than the frequency of the colour of pad β, then Pahom figure can walk from α to β during the walk from the red pad to the violet pad
2. If pad α and pad β have a common intersection and the frequency of the colour of pad α is strictly greater than the frequency of the colour of pad β, then Pahom figure can walk from α to β during the walk from the violet pad to the red pad
3. A coloured pad, with the exception of the red pad, disappears from display when the Pahom figure walks away from it.
The developer of the game has programmed all the whizzbang features of the game. All that is left is to ensure that Pahom has a chance to succeed in each instance of the game (that is, there is at least one valid walk from the red pad to the violet pad and then back again to the red pad.) Your task is to write a program to check whether at least one valid path exists in each instance of the game.
 

Input
The input starts with an integer K (1 <= K <= 50) indicating the number of scenarios on a line by itself. The description for each scenario starts with an integer N (2 <= N <= 300) indicating the number of pads, on a line by itself, followed by N lines that describe the colors, locations and sizes of the N pads. Each line contains the frequency, followed by the x- and y-coordinates of the pad's center and then the radius. The frequency is given as a real value with no more than three decimal places. The coordinates and radius are given, in meters, as integers. All values are separated by a single space. All integer values are in the range of -10,000 to 10,000 inclusive. In each scenario, all frequencies are in the range of 400.0 to 789.0 inclusive. Exactly one pad will have a frequency of “400.0” and exactly one pad will have a frequency of “789.0”.
 

Output
The output for each scenario consists of a single line that contains: Game is VALID, or Game is NOT VALID
 

Sample Input
2 2 400.0 0 0 4 789.0 7 0 2 4 400.0 0 0 4 789.0 7 0 2 500.35 5 0 2 500.32 5 0 3
 

Sample Output
Game is NOT VALID Game is VALID
 
醉了,花了10分钟才理解题意。。。

简单的说下题意吧,有的细节不准确。

图上有N个圆形的光谱,一个人想从红色圆谱到紫罗兰圆谱,再由紫罗兰光谱返回红色光谱。图中可能需要经过其它的圆形光谱,现在给出如下限制:

1,红色光谱和紫罗兰光谱允许走两次,其它的光谱若走过一次不能再走。

2,对于任意的光谱A和光谱B,只要两个光谱相交,就可以从光谱频率大的圆经过光谱频率小的圆。

问你这个人能不能实现这个过程。


思路:建立超级源点0,超级汇点N + 1.

一:源点连接紫罗兰光谱,边权为2。
二:红色光谱连接汇点,边权为2。
三:对于任意相交的两个光谱,从频率大的引一条到频率小的边,边权为1。

最后从超级源 到 超级汇 跑一下最大流,看Maxflow 是否为2。若为2就说明可以实现,否则不能实现。

AC代码:

#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#define MAXN 1000+10
#define MAXM 200000+1000
#define INF 100000000
#define eps 1e-5
#define DD double
using namespace std;
struct Edge
{
    int from, to, cap, flow, next;
};
Edge edge[MAXM];
struct pad
{
    DD THz, x, y, r;
};
pad num[MAXN];
int head[MAXN], edgenum;
int cur[MAXN];
int dist[MAXN];
bool vis[MAXN];
int N;
int sx, ex;//源点 汇点
void init()
{
    edgenum = 0;
    memset(head, -1, sizeof(head));
}
void input()
{
    for(int i = 1; i <= N; i++)
        scanf("%lf%lf%lf%lf", &num[i].THz, &num[i].x, &num[i].y, &num[i].r);
}
void addEdge(int u, int v, int w)
{
    Edge E1 = {u, v, w, 0, head[u]};
    edge[edgenum] = E1;
    head[u] = edgenum++;
    Edge E2 = {v, u, 0, 0, head[v]};
    edge[edgenum] = E2;
    head[v] = edgenum++;
}
bool judge(DD THz1, DD x1, DD y1, DD r1, DD THz2, DD x2, DD y2, DD r2)//判断是否相交
{//圆心距离小于半径之和
    return ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) < (r1 + r2) * (r1 + r2)) && THz1 > THz2;
}
void getMap()
{
    sx = 0, ex = N + 1;//建立超级源点0,超级汇点N+1
    for(int i = 1; i <= N; i++)
    {
        if(abs(num[i].THz - 789.0) <= eps)
            addEdge(0, i, 2);//超级源点连接紫罗兰 边权为2
        if(abs(num[i].THz - 400.0) <= eps)
            addEdge(i, N + 1, 2);//红色连接超级汇点 边权为2
        for(int j = 1; j <= N; j++)
        {
            if(i == j) continue;
            if(judge(num[i].THz, num[i].x, num[i].y, num[i].r, num[j].THz, num[j].x, num[j].y, num[j].r))
                addEdge(i, j, 1);////相交 且满足THz 的 大于关系 建边且边权为1
        }
    }
}
bool BFS(int start, int end)
{
    queue<int> Q;
    memset(dist, -1, sizeof(dist));
    memset(vis, false, sizeof(vis));
    dist[start] = 0;
    vis[start] = true;
    Q.push(start);
    while(!Q.empty())
    {
        int u = Q.front();
        Q.pop();
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            Edge E = edge[i];
            if(!vis[E.to] && E.cap > E.flow)
            {
                vis[E.to] = true;
                dist[E.to] = dist[u] + 1;
                if(E.to == end) return true;
                Q.push(E.to);
            }
        }
    }
    return false;
}
int DFS(int x, int a, int end)
{
    if(x == end || a == 0) return a;
    int flow = 0, f;
    for(int &i = cur[x]; i != -1; i = edge[i].next)
    {
        Edge &E = edge[i];
        if(dist[E.to] == dist[x] + 1 && (f = DFS(E.to, min(E.cap - E.flow, a), end)) > 0)
        {
            E.flow += f;
            edge[i^1].flow -= f;
            flow += f;
            a -= f;
            if(a == 0) break;
        }
    }
    return flow;
}
int Maxflow(int start, int end)
{
    int flow = 0;
    while(BFS(start, end))
    {
        memcpy(cur, head, sizeof(head));
        flow += DFS(start, INF, end);
    }
    return flow;
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &N);
        init();
        input();
        getMap();
        if(Maxflow(0, N + 1) == 2)
            printf("Game is VALID\n");
        else
            printf("Game is NOT VALID\n");
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值