HDU3622.Bomb Game——2-sat二分最大值+可行性判定

来源:互联网 发布:apache logo 编辑:程序博客网 时间:2024/06/05 13:27

http://acm.hdu.edu.cn/showproblem.php?pid=3622

题目描述:
有n个给n对炸弹可以放置的位置(每个位置为一个二维平面上的点),每次放置炸弹是时只能选择这一对中的其中一个点,每个炸弹爆炸的范围半径都一样,控制爆炸的半径使得所有的爆炸范围都不相交(可以相切),求解这个最大半径.
首先二分最大半径值,然后2-sat构图判断其可行性,对于每两对位置(u,uu)和(v,vv),如果u和v之间的距离小于2*id,也就是说位置u和位置v处不能同时防止炸弹(两范围相交),所以连边(u,vv)和(v,uu),求解强连通分量判断可行性.

#include<cstring>#include<cstdio>#include<cmath>#include<algorithm>const int MAXN=210;const int MAXM=41000;const double eps=1e-5;using namespace std;struct node{    int x,y;}p[MAXN];struct Edge{    int to,next;}edge[MAXM<<1];int head[MAXN],tot;void init(){    tot=0;    memset(head,0xff,sizeof(head));}void addedge(int u,int v){    edge[tot].to=v;    edge[tot].next=head[u];    head[u]=tot++;}int low[MAXN],dfn[MAXN],sccno[MAXN],scc_cnt,dfs_clock;int Stack[MAXN],top;bool instack[MAXN];void dfs(int u){    int v;    Stack[top++]=u;    instack[u]=1;    low[u]=dfn[u]=++dfs_clock;    for(int i=head[u];i!=-1;i=edge[i].next){        v=edge[i].to;        if(!dfn[v]){            dfs(v);            low[u]=min(low[u],low[v]);        }        else if(instack[v]&&low[u]>dfn[v]){            low[u]=dfn[v];        }    }    if(low[u]==dfn[u]){        ++scc_cnt;        for(;;){            v=Stack[--top];            instack[v]=0;            sccno[v]=scc_cnt;            if(v==u) break;        }    }}bool solveable(int n){    memset(dfn,0,sizeof(dfn));    memset(instack,false,sizeof(instack));    dfs_clock=scc_cnt=top=0;    for(int i=0;i<n;++i){        if(!dfn[i]) dfs(i);    }    for(int i=0;i<n;i+=2){        if(sccno[i]==sccno[i^1])            return false;    }    return true;}double dist(node a,node b){    return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}void Build_graph(int n,double m){    init();    for(int i=0;i<2*n;++i){        for(int j=0;j<2*n;++j){            if(i/2!=j/2&&dist(p[i],p[j])<m){                addedge(i,j^1);                addedge(j,i^1);            }        }    }}int main(){#ifndef ONLINE_JUDGEfreopen("in.txt","r",stdin);#endif // ONLINE_JUDGE    int n;    while(scanf("%d",&n)!=EOF){        for(int i=0;i<n;++i){            scanf("%d%d%d%d",&p[2*i].x,&p[2*i].y,&p[2*i+1].x,&p[2*i+1].y);        }        double  l=0.0,r=40000.0;        while(r-l>=eps){            double m=(l+r)/2.0;            Build_graph(n,2*m);            if(solveable(2*n)) l=m;            else r=m;        }        printf("%.2lf\n",l);    }    return 0;}
0 0
原创粉丝点击