hdu 4183 Pahom on Water(最大流)

题意:二维空间上有一些点,每个点有一个半径r和频率f,要从某一个点S走到另一个点T,然后再从T回到S。从S到T时,如果两个点表示的圆相交并且第一个点小于第二个点的频率的,那么能从第一个点到第二个点,从T到S时,第一个点的频率要大于第二个点的频率。除了S和T,每个点走后就会消失,问是否存在一种走法。

思路:这题最开始看题看的晕了,其实不是很难,被我写的非常恶心。。。可以发现如果从S可以到T,那么顺着这个路径返回,就是从T到S的路径,那么就变成从S到T是否存在一条以上的路径使得不经过重复的点。把每个点拆点,连一条容量为1的边就能解决了。


代码:


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=1000+10;
const int maxm=100000+10;
const double sp=400.0;
const double tp=789.0;
struct Edge
{
    int to,cap,flow,next;
    Edge(){}
    Edge(int to,int cap,int flow,int next):to(to),cap(cap),flow(flow),next(next){}
}edges[maxm<<1];
int head[maxn],cur[maxn],d[maxn],nEdge,n;
void AddEdges(int from,int to,int cap)
{
    edges[++nEdge]=Edge(to,cap,0,head[from]);
    head[from]=nEdge;
    edges[++nEdge]=Edge(from,0,0,head[to]);
    head[to]=nEdge;
}
bool BFS(int s,int t)
{
    memset(d,0xff,sizeof(d));
    d[s]=0;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int k=head[u];k!=-1;k=edges[k].next)
        {
            Edge e=edges[k];
            if(d[e.to]==-1&&e.cap>e.flow)
            {
                d[e.to]=d[u]+1;
                q.push(e.to);
            }
        }
    }
    return d[t]!=-1;
}
int DFS(int u,int a,int t)
{
    if(u==t||a==0) return a;
    int flow=0,f;
    for(int &k=cur[u];k!=-1;k=edges[k].next)
    {
        Edge e =edges[k];
        if(d[e.to]==d[u]+1&&(f=DFS(e.to,min(a,e.cap-e.flow),t))>0)
        {
            edges[k].flow+=f;
            edges[k^1].flow-=f;
            flow+=f;a-=f;
            if(a==0) break;
        }
    }
    return flow;
}
int MaxFlow(int s,int t)
{
    int flow=0;
    while(BFS(s,t))
    {
        for(int i=0;i<=n*2+1;++i) cur[i]=head[i];
        flow+=DFS(s,inf,t);
    }
    return flow;
}
struct Point
{
    double f,x,y,r;
    void read()
    {
        scanf("%lf%lf%lf%lf",&f,&x,&y,&r);
    }
}point[maxn];
int dcmp(double x)
{
    if(fabs(x)<eps) return 0;
    return x>0?1:-1;
}
double Dis(Point a,Point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool check(Point a,Point b)
{
    double d=Dis(a,b);
    return dcmp(d-a.r-b.r)<=0;
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        memset(head,0xff,sizeof(head));
        nEdge=-1;
        int S,T;
        for(int i=1;i<=n;++i)
        {
            point[i].read();
            if(dcmp(point[i].f-sp)==0) S=i;
            else if(dcmp(point[i].f-tp)==0) T=i;
        }
        int tmp;
        for(int i=1;i<=n;++i)
        {
            if(i==S) AddEdges(i,i+n,inf);
            else AddEdges(i,i+n,1);
            for(int j=1;j<=n;++j)
            {
                if(i==j) continue;
                if(!check(point[i],point[j])) continue;
                tmp=dcmp(point[i].f-point[j].f);
                if(tmp<0)
                    AddEdges(i+n,j,1);
            }
        }
        int ans=MaxFlow(S,T);
        if(ans>=2||check(point[S],point[T]))
            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、付费专栏及课程。

余额充值