ZOJ 3717 Balloon
_(:3」∠)_
就是很裸的一道2-SAT问题,比赛的时候忘记加同一对里的边,也没注意到最后的进位问题,所以搓了。
计算所有点之间的距离,排序后二分建图,二分的判断条件就是2-SAT。
#include<cstdio> #include<cstring> #include<vector> #include<algorithm> #include<iostream> #include<cmath> using namespace std; const int N=410; struct Point { int x,y,z; }point[N]; struct Dis { int dis,x,y; }d[N*N]; int n,dlen; vector<int> G[N<<1]; bool mark[N<<1]; int s[N<<1],cnt; bool DFS(int x) { if(mark[x^1]) return false; if(mark[x]) return true; mark[x]=true; s[cnt++]=x; for(int i=0;i<G[x].size();++i) if(!DFS(G[x][i])) return false; return true; } bool solve() { for(int i=2;i<=n*2;i+=2) { if(!mark[i]&&!mark[i+1]) { cnt=0; if(!DFS(i)) { while(cnt) mark[s[--cnt]]=false; if(!DFS(i+1)) return false; } } } return true; } int dist(int i,int j) { return (point[i].x-point[j].x)*(point[i].x-point[j].x)+ (point[i].y-point[j].y)*(point[i].y-point[j].y)+ (point[i].z-point[j].z)*(point[i].z-point[j].z); } bool cmp(Dis A,Dis B) { return A.dis<B.dis; } void init() { for(int i=0;i<=n*2;++i) G[i].clear(); memset(mark,false,sizeof mark); } bool judge(int mid) { int x,y; init(); int t=n/2; for(int i=1;i<=t;++i) { x=i*2; y=(t+i)*2; G[x].push_back(y^1); G[y].push_back(x^1); } for(int i=0;i<mid;++i) { x=d[i].x; y=d[i].y; x*=2; y*=2; G[x^1].push_back(y); G[y^1].push_back(x); } return solve(); } int main() { int x,y; bool flag; int ans,np; int L,R,mid; double hehe; while(scanf("%d",&n)==1) { init(); dlen=0; for(int i=1;i<=n;++i) { scanf("%d%d%d%d%d%d",&point[i].x,&point[i].y,&point[i].z, &point[i+n].x,&point[i+n].y,&point[i+n].z); } n*=2; for(int i=1;i<=n;++i) { for(int j=i+1;j<=n;++j) { d[dlen].x=i; d[dlen].y=j; d[dlen++].dis=dist(i,j); } } sort(d,d+dlen,cmp); ans=d[0].dis; np=0; L=0,R=dlen-1; while(L<=R) { mid=L+(R-L)/2; if(judge(mid)) { L=mid+1; ans=d[mid].dis; } else R=mid-1; } hehe=sqrt(double(ans))/2; printf("%.3lf\n",(int)(hehe*1000)/1000.0); } }