zoukankan      html  css  js  c++  java
  • 【POJ3683】Priest John's Busiest Day

    题目大意:给定 N 个操作,每个操作占用两个区间中的任意一个即可,求是否可以满足 N 项操作,且使得操作区间不重叠,若可以,输出一种具体方案。

    题解:2-sat 模板题,区间覆盖的位置有些毒瘤,貌似题意没交代清楚?

    代码如下

    #include <cstdio>
    #include <vector>
    #include <utility>
    #include <ctype.h>
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define all(x) x.begin(),x.end()
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> P;
    const int mod=1e9+7;
    const int inf=0x3f3f3f3f;
    const int maxn=2010;
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    inline ll sqr(ll x){return x*x;}
    inline ll read(){
    	ll x=0,f=1;char ch;
    	do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
    	do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
    	return f*x;
    }
    
    vector<int> G[maxn];
    int dfs_clk,dfn[maxn],low[maxn],stk[maxn],in[maxn],top;
    int scc,cor[maxn];
    int n,st[maxn],ed[maxn],len[maxn];
    char s[10];
    
    bool overlap(int a, int b, int c, int d) {
    	if (a >= c&&a<d || b>c&&b <= d || a <= c&&b >= d) return 1;
    	return 0;
    }
    
    void read_and_parse(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%s",s+1);
    		st[i]=((s[1]-'0')*10+s[2]-'0')*60+(s[4]-'0')*10+s[5]-'0';
    		scanf("%s",s+1);
    		ed[i]=((s[1]-'0')*10+s[2]-'0')*60+(s[4]-'0')*10+s[5]-'0';
    		scanf("%d",&len[i]);
    	}
    	for(int i=1;i<=n;i++)
    		for(int j=i+1;j<=n;j++){
    			if(overlap(st[i],st[i]+len[i],st[j],st[j]+len[j]))G[i].pb(j+n),G[j].pb(i+n);
    			if(overlap(st[i],st[i]+len[i],ed[j]-len[j],ed[j]))G[i].pb(j),G[j+n].pb(i+n);
    			if(overlap(ed[i]-len[i],ed[i],st[j],st[j]+len[j]))G[i+n].pb(j+n),G[j].pb(i);
    			if(overlap(ed[i]-len[i],ed[i],ed[j]-len[j],ed[j]))G[i+n].pb(j),G[j+n].pb(i);
    		}
    }
    
    void tarjan(int u){
    	low[u]=dfn[u]=++dfs_clk;
    	stk[++top]=u,in[u]=1;
    	for(int i=0;i<G[u].size();i++){
    		int v=G[u][i];
    		if(!dfn[v])tarjan(v),low[u]=min(low[u],low[v]);
    		else if(in[v])low[u]=min(dfn[v],low[u]);
    	}
    	if(low[u]==dfn[u]){
    		++scc;int v;
    		do{
    			v=stk[top--],in[v]=0;
    			cor[v]=scc;
    		}while(u!=v);
    	}
    }
    
    void solve(){
    	for(int i=1;i<=n<<1;i++)if(!dfn[i])tarjan(i);
    	for(int i=1;i<=n;i++)if(cor[i]==cor[i+n])return (void)puts("NO");
    	puts("YES");
    	for(int i=1;i<=n;i++){
    		if(cor[i]<cor[i+n])
    			printf("%02d:%02d %02d:%02d
    ",st[i]/60,st[i]%60,(st[i]+len[i])/60,(st[i]+len[i])%60);
    		else
    			printf("%02d:%02d %02d:%02d
    ",(ed[i]-len[i])/60,(ed[i]-len[i])%60,ed[i]/60,ed[i]%60);
    	}
    }
    
    int main(){
    	read_and_parse();
    	solve();
    	return 0;
    }
    
    
  • 相关阅读:
    《CMake实践》笔记二:INSTALL/CMAKE_INSTALL_PREFIX
    《CMake实践》笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE
    《CMake实践》第三部分的示例代码的错误
    利用 autoconf 和 automake 生成 Makefile 文件
    如何安装 罗技“优联技术”无线鼠标、无线键盘?
    make 和 makefile 的关系
    编译器 cc、gcc、g++、CC 的区别
    如何撤销 PhpStorm/Clion 等 JetBrains 产品的 “Mark as Plain Text” 操作 ?
    Linux/Ubuntu tree 命令以树形结构显示文件夹目录结构
    C/C++ 静态链接库(.a) 与 动态链接库(.so)
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10633170.html
Copyright © 2011-2022 走看看