HDU4183 Pahom on Water(网络流之最大流)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4183

题意:给你n个点,每个点有一个频率,原点坐标和半径,i到j可达当且仅当i的频率小于j的频率并且两个圆相交,问你从最小的频率到最大的频率,再从最大的频率到最小的频率的方案是否成立(每条边只能使用一次)。

思路:起点-终点,终点-起点其实就是起点-终点是否有两条以上不同的路径,因为每条边只能使用一次,所以权值为1,然后暴力建图跑下最大流模板就可以了。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
using namespace std;
#define N 310
#define M 90010
#define inf 1000000007
typedef struct
{
    int v,w,next;
}Node;
Node e[M];
typedef struct
{
    int x,y,r;
    double f;
}node;
node s[N];
int head[N],vis[N],d[N];
int n,tot;
int cmp(node u,node v)
{
    return u.f<v.f;
}
void add(int x,int y,int z)
{
    e[tot].v=y;
    e[tot].w=z;
    e[tot].next=head[x];
    head[x]=tot++;
}
int check(int a,int b)
{
    double t,ans;
    t=(s[a].x-s[b].x)*(s[a].x-s[b].x)+(s[a].y-s[b].y)*(s[a].y-s[b].y);
    ans=sqrt(t)-s[a].r-s[b].r;
    if(ans>0)
    return 0;
    return 1;
}
int bfs(int x,int y){
    int i,j,k,t;
    memset(d,-1,sizeof(d));
    queue<int> q;
    q.push(x);
    d[x]=0;
    while(!q.empty()){
        t=q.front();
        q.pop();
        for(i=head[t];i!=-1;i=e[i].next){
            j=e[i].v;
            k=e[i].w;
            if(k&&d[j]==-1){
                d[j]=d[t]+1;
                if(j==y)
                    return 1;
                q.push(j);
            }
        }
    }
    return 0;
}
int dfs(int x,int y,int z){
    if(x==y)
        return z;
    int i,j,k,ans=0;
    for(i=vis[x];i!=-1;i=e[i].next){
        j=e[i].v;
        k=e[i].w;
        if(d[j]==d[x]+1){
            k=dfs(j,y,min(z-ans,k));
            e[i].w-=k;
            e[i^1].w+=k;
            ans+=k;
            if(e[i].w)
                vis[x]=i;
            if(ans==z)
                return ans;
        }
    }
    if(ans==0)
        d[x]=-1;
    return ans;
}
int dinic(int x,int y){
    int ans=0;
    while(bfs(x,y)){
        memcpy(vis,head,sizeof(head));
        ans=ans+dfs(x,y,inf);
    }
    return ans;
}
int main()
{
    int i,j,k,t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        tot=0;
        memset(head,-1,sizeof(head));
        for(i=0;i<n;i++)
            scanf("%lf%d%d%d",&s[i].f,&s[i].x,&s[i].y,&s[i].r);
        sort(s,s+n,cmp);
        for(i=0;i<n;i++)
        for(j=i+1;j<n;j++)
        if(check(i,j))
        {
            add(i,j,1);
            add(j,i,0);
        }
        if(dinic(0,n-1)>=2)
            printf("Game is VALID\n");
        else
            printf("Game is NOT VALID\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37751662/article/details/80056546