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); } }