hdu3622 二分+2sat

来源:互联网 发布:mac的复制黏贴快捷键 编辑:程序博客网 时间:2024/05/16 11:34
题意:
     给你N组炸弹,每组2个,让你在这N组里面选取N个放置,要求(1)每组只能也必须选取一个(2)炸弹与炸弹之间的半径相等(3)不能相互炸到对方。求最大的可放置半径。


思路:

     二分去枚举半径,然后用2sat去判断是否可行,在2sat里,每组炸弹的两个是正常对,任何两组的任何两个距离小于等于mid那么这两个是矛盾对。这样强连通缩短,然后判断有没有一组是在同一个强连通块里的,没有那么就ok继续更新二分查找答案。

#include<stdio.h>#include<string.h>#include<math.h>#include<stack>#define N_node 200 + 10#define N_edge 100000 + 100using namespace std;typedef struct{   int to ,next;}STAR;typedef struct{   double x1 ,x2 ,y1 ,y2;}NODE;STAR E1[N_edge] ,E2[N_edge];NODE node[111];int list1[N_node] ,list2[N_node] ,tot;int Belong[N_node] ,cnt;int mark[N_node];stack<int>st;void add(int a , int b){   E1[++tot].to = b;   E1[tot].next = list1[a];   list1[a] = tot;      E2[tot].to = a;   E2[tot].next = list2[b];   list2[b] = tot;}void DFS1(int s){   mark[s] = 1;   for(int k = list1[s] ;k ;k = E1[k].next)   {      int xin = E1[k].to;      if(!mark[xin]) DFS1(xin);   }   st.push(s);}void DFS2(int s){   mark[s] = 1;   Belong[s] = cnt;   for(int k = list2[s] ;k ;k = E2[k].next)   {      int xin = E2[k].to;      if(!mark[xin]) DFS2(xin);   }}double diss(double x1 ,double y1 ,double x2 ,double y2){   double tmp = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);   return sqrt(tmp);}                                          bool ok(double mid ,int n){   memset(list1 ,0 ,sizeof(list1));   memset(list2 ,0 ,sizeof(list2));   tot = 1;   for(int i = 0 ;i < n ;i ++)   for(int j = i + 1 ;j < n ;j ++)   {      int a ,b;      double dis = diss(node[i].x1 ,node[i].y1 ,node[j].x1 ,node[j].y1);      if(dis <= mid)      {         a = i * 2 ,b = j * 2;         add(a ,b^1) ,add(b ,a^1);      }      dis = diss(node[i].x1 ,node[i].y1 ,node[j].x2 ,node[j].y2);      if(dis <= mid)      {         a = i * 2 ,b = j * 2 + 1;         add(a ,b^1) ,add(b ,a^1);      }      dis = diss(node[i].x2 ,node[i].y2 ,node[j].x1 ,node[j].y1);      if(dis <= mid)      {         a = i * 2 + 1,b = j * 2;         add(a ,b^1) ,add(b ,a^1);      }      dis = diss(node[i].x2 ,node[i].y2 ,node[j].x2 ,node[j].y2);      if(dis <= mid)      {         a = i * 2 + 1,b = j * 2 + 1;         add(a ,b^1) ,add(b ,a^1);      }   }   memset(mark ,0 ,sizeof(mark));   while(!st.empty())st.pop();   for(int i = 0 ;i < n * 2 ;i ++)   if(!mark[i]) DFS1(i);   memset(mark ,0 ,sizeof(mark));   cnt = 0;   while(!st.empty())   {      int xin = st.top();      st.pop();      if(mark[xin]) continue;      ++cnt;      DFS2(xin);   }   int mk = 0;   for(int i = 0 ;i < n * 2 ;i += 2)   {      if(Belong[i]  == Belong[i^1])      mk = 1;   }   return !mk;}int main (){    int n ,i;    while(~scanf("%d" ,&n))    {       for(i = 0 ;i < n ;i ++)       scanf("%lf %lf %lf %lf" ,&node[i].x1 ,&node[i].y1 ,&node[i].x2 ,&node[i].y2);       double low ,mid ,up ,ans = 0;       low = 0 ,up = 2000000000;       for(i = 1 ;i <= 100 ;i ++)       {            mid = (low + up) / 2;            if(ok(mid ,n))            ans = low = mid;            else up = mid;       }       printf("%.2lf\n" ,ans/2);   }   return 0;}       

0 0
原创粉丝点击