POJ_2296题解

来源:互联网 发布:淘宝一口价能随便改吗 编辑:程序博客网 时间:2024/05/16 08:16

解法:2-SAT问题

二分枚举边长=mid,当abs(x[i]-x[j])<mid且abs(y[i]-y[j])<2*mid时,才需要加边。

记2*i为正方形放在上面,2*i+1为正方形放在下面。

当abs(y[i]-y[j])>=mid时,不妨假设y[i]>y[j],则需要添加边2*i+1->2*j和2*j->2*i。

当0<abs(y[i]-y[j])<mid时,不妨假设y[i]>y[j],则一定要一上一下的放正方形,故需要添加边2*i+1->2*i和2*j->2*j+1。

当y[i]==y[j]时,需要一上一下放,当不强制要求谁上谁下,故需要添加边2*i->2*j+1和2*i+1->2*j和2*j->2*i+1和2*j+1->2*i。


//time:16ms//memory:320K#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<stack>#include<queue>using namespace std;const int N=210;int n,m,cnt,num;vector<int> G[N];int pre[N],scc[N],low[N];int x[N],y[N];stack<int> s;void init(){cnt=0,num=0;memset(pre,0,sizeof pre);memset(scc,0,sizeof scc);while(!s.empty()) s.pop();for(int i=0;i<(m<<1);++i)G[i].clear();}void DFS(int u){pre[u]=low[u]=++num;s.push(u);for(int i=0;i<G[u].size();++i) {int v=G[u][i];if(!pre[v]) {DFS(v);low[u]=min(low[u],low[v]);}else if(!scc[v]) low[u]=min(low[u],pre[v]);}if(pre[u]==low[u]) {int tmp=-1;++cnt;while(tmp!=u) {tmp=s.top();s.pop();scc[tmp]=cnt;}}}bool Targin(){for(int i=0;i<(m<<1);++i)if(!pre[i]) DFS(i);for(int i=0;i<m;++i)if(scc[i<<1]==scc[i<<1|1])return false;return true;}int main(){int _;int L,R,mid;scanf("%d",&_);while(_--) {scanf("%d",&m);for(int i=0;i<m;++i)scanf("%d%d",x+i,y+i);L=1,R=20000;while(L<R){init();mid=L+((R-L+1)>>1);for(int i=0;i<m;++i)for(int j=i+1;j<m;++j) {if(abs(x[i]-x[j])<mid&&abs(y[i]-y[j])<(mid<<1)) {if(abs(y[i]-y[j])>=mid) {if(y[i]>y[j]) {G[i<<1|1].push_back(j<<1|1);G[j<<1].push_back(i<<1);}else {G[j<<1|1].push_back(i<<1|1);G[i<<1].push_back(j<<1);}}else if(y[i]>y[j]) {G[i<<1|1].push_back(i<<1);G[j<<1].push_back(j<<1|1);}else if(y[j]>y[i]) {G[j<<1|1].push_back(j<<1);G[i<<1].push_back(i<<1|1);}else {G[i<<1].push_back(j<<1|1);G[j<<1|1].push_back(i<<1);G[j<<1].push_back(i<<1|1);G[i<<1|1].push_back(j<<1);}}}if(Targin()) L=mid;else R=mid-1;}printf("%d\n",L);}}


原创粉丝点击