D45 2-SAT+二分 UVA1146 Now or later

视频链接:D45 2-SAT+二分 UVA1146 Now or later_哔哩哔哩_bilibili

 

 

D40 2-SAT POJ3683 Priest John's Busiest Day - 董晓 - 博客园 (cnblogs.com)

UVA1146 Now or later - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

https://vjudge.net/problem/UVA-1146

// 2-SAT+二分 O(n*n*logt)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

const int N=4010;
int n,t[N][2];
vector<int> v[N]; //邻接表
int dfn[N],low[N],scc[N],stk[N],tim,top,cnt;

void tarjan(int x){
  dfn[x]=low[x]=++tim;
  stk[++top]=x;
  for(int y:v[x]){
    if(!dfn[y]){ //若y尚未访问
      tarjan(y);
      low[x]=min(low[x],low[y]);
    }
    else if(!scc[y]) //若y已访问且未处理
      low[x]=min(low[x],dfn[y]);
  }
  
  if(low[x]==dfn[x]){ //若x是SCC的根
    ++cnt;
    for(int y=-1;y!=x;)
      scc[y=stk[top--]]=cnt;
  }
}
bool check(int mid){
  for(int i=1;i<=2*n;++i) v[i].clear();
  memset(dfn,0,sizeof dfn);
  memset(low,0,sizeof low);
  memset(scc,0,sizeof scc);
  tim=top=cnt=0;
  
  for(int i=1;i<=n;++i){ //建图: 注意逆否与对称
    for(int j=i+1;j<=n;++j){
      if(abs(t[i][0]-t[j][0])<mid) //i,j都早不行
        v[i].push_back(j+n), //i早→j晚
        v[j].push_back(i+n); //j早→i晚
      if(abs(t[i][0]-t[j][1])<mid) //i早,j晚不行
        v[i].push_back(j),    //i早→j早
        v[j+n].push_back(i+n);//j晚→i晚       
      if(abs(t[i][1]-t[j][0])<mid) //i晚,j早不行
        v[i+n].push_back(j+n),//i晚→j晚
        v[j].push_back(i);    //j早→i早
      if(abs(t[i][1]-t[j][1])<mid) //i,j都晚不行
        v[i+n].push_back(j), //i晚→j早
        v[j+n].push_back(i); //j晚→i早      
    }
  }
  
  for(int i=1;i<=2*n;++i) if(!dfn[i])tarjan(i);
  for(int i=1;i<=n;++i)
    if(scc[i]==scc[i+n]) return 0;
  return 1;
}
int main(){
  while(scanf("%d",&n)!=EOF){
    for(int i=1;i<=n;++i)
      scanf("%d%d",&t[i][0],&t[i][1]);
      
    int l=0,r=1e7+1,mid; //二分时间
    while(l+1<r){ 
      mid=(l+r)>>1;
      check(mid)?l=mid:r=mid;
    }
    printf("%d\n",l);   
  }
}

 

// 2-SAT+二分 O(n*n*logt)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

const int N=4010;
int n,t[N][2];
vector<int> v[N]; //邻接表
int dfn[N],low[N],scc[N],stk[N],tim,top,cnt;

void tarjan(int x){
  dfn[x]=low[x]=++tim;
  stk[++top]=x;
  for(int y:v[x]){
    if(!dfn[y]){ //若y尚未访问
      tarjan(y);
      low[x]=min(low[x],low[y]);
    }
    else if(!scc[y]) //若y已访问且未处理
      low[x]=min(low[x],dfn[y]);
  }
  
  if(low[x]==dfn[x]){ //若x是SCC的根
    ++cnt;
    for(int y=-1;y!=x;)
      scc[y=stk[top--]]=cnt;
  }
}
bool check(int mid){
  for(int i=1;i<=2*n;++i) v[i].clear();
  memset(dfn,0,sizeof dfn);
  memset(low,0,sizeof low);
  memset(scc,0,sizeof scc);
  tim=top=cnt=0;
  
  for(int i=1;i<=n;++i){ //建图: 注意对称
    for(int j=1;j<=n;++j)if(i!=j){
      if(abs(t[i][0]-t[j][0])<mid) //i,j都早不行
        v[i].push_back(j+n); //i早→j晚
      if(abs(t[i][0]-t[j][1])<mid) //i早,j晚不行
        v[i].push_back(j);    //i早→j早
      if(abs(t[i][1]-t[j][0])<mid) //i晚,j早不行
        v[i+n].push_back(j+n);//i晚→j晚
      if(abs(t[i][1]-t[j][1])<mid) //i,j都晚不行
        v[i+n].push_back(j); //i晚→j早
    }
  }
  
  for(int i=1;i<=2*n;++i) if(!dfn[i])tarjan(i);
  for(int i=1;i<=n;++i)
    if(scc[i]==scc[i+n]) return 0;
  return 1;
}
int main(){
  while(scanf("%d",&n)!=EOF){
    for(int i=1;i<=n;++i)
      scanf("%d%d",&t[i][0],&t[i][1]);
      
    int l=0,r=1e7+1,mid; //二分时间
    while(l+1<r){ 
      mid=(l+r)>>1;
      check(mid)?l=mid:r=mid;
    }
    printf("%d\n",l);   
  }
}

 

posted @ 2024-08-17 18:15  董晓  阅读(74)  评论(0编辑  收藏  举报