• POJ


    题意:有N个婚礼,每个婚礼可以在两段时间内举行,要求N段婚礼的时间没有相交,可行则输出方案
    分析:2-SAT求解.建图就是若婚礼i的第一段时间与婚礼j的第一段时间相交则选i1则必选j2,以此类推.
    Tarjan跑出强联通分量之后,反向缩点建边并染色,最后输出可行解
    2-SAT输出方案可作为模板,其思路参考博客:https://blog.csdn.net/Hawo11/article/details/74908233

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<stack>
    using namespace std;
    typedef long long LL;
    const int maxn = 1e5+10;
    const int MAXM = 2e6+5;
    struct Edge{
        int v,next;
    }edges[MAXM],E[MAXM];
    int head[maxn],tot;
    int H[maxn],tt;
    stack<int> S;
    int pre[maxn],low[maxn],sccno[maxn],dfn,scc_cnt,ind[maxn],col[maxn];
    void init()
    {
        tt = tot = dfn = scc_cnt=0;
        memset(H,-1,sizeof(H));
        memset(pre,0,sizeof(pre));
        memset(sccno,0,sizeof(sccno));
        memset(head,-1,sizeof(head));
        memset(ind,0,sizeof(ind));
    }
    void AddEdge(int u,int v)   {
        edges[tot] = (Edge){v,head[u]};
        head[u] = tot++;
    }
    
    void nAddEdge(int u,int v){
        E[tt] = (Edge){v,H[u]};
        H[u] = tt++;
    }
    
    void Tarjan(int u)
    {
        int v;
        pre[u]=low[u]=++dfn;
        S.push(u);
        for(int i=head[u];~i;i=edges[i].next){
            v= edges[i].v;
            if(!pre[v]){
                Tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(!sccno[v]){
                low[u]=min(low[u],pre[v]);
            }
        }
        if(pre[u]==low[u]){
            int x;
            ++scc_cnt;
            for(;;){
                x = S.top();S.pop();
                sccno[x]=scc_cnt;
                if(x==u)break;
            }
        }
    }
    
    int con[maxn];
    
    
    struct Node{
        int st,ed;
    }p[2005];
    int N,all;
    #include<queue>
    void solve()
    {
        int a,b;
        for(int i=0;i<all;++i){
            if(!pre[i]) Tarjan(i);
        }
        for(int i=0;i<all;i+=2){
            if(sccno[i]==sccno[i^1]){
                printf("NO
    ");
                return;
            }
            a = sccno[i], b = sccno[i^1];
            con[a] = b;
            con[b] = a;
        }
        printf("YES
    ");
        //缩点
        for(int u=0;u<all;++u){
            a = sccno[u];
            for(int i = head[u];~i;i=edges[i].next){
                int v = edges[i].v;
                b = sccno[v];
                if(a!=b){
                    nAddEdge(b,a);
                    ind[a]++;
                }
            }
        }
        //逆拓扑排xu
        queue<int> Q;
        memset(col,0,sizeof(col));
        for(int i=1;i<=scc_cnt;++i){
            if(!ind[i]) Q.push(i);
        }
        while(!Q.empty()){
            int u  =Q.front(); Q.pop();
            if(!col[u]){
                col[u] = 1;
                col[con[u]] = 2;
            }
            for(int i=H[u];~i;i=E[i].next){
                int v = E[i].v;
                ind[v]--;
                if(!ind[v]){
                    Q.push(v);
                }
            }
        }
    
        int h1,m1,h2,m2;
        for(int i=0;i<all;i+=2){
            int pt;
            if(col[sccno[i]]== 1) pt = i;
            else pt = i^1;
            h1 = p[pt].st/60,m1 =p[pt].st %60;
            h2 = p[pt].ed/60,m2 =p[pt].ed %60;
            printf("%02d:%02d %02d:%02d
    ",h1,m1,h2,m2);
        }
    }
    
    bool check(int i,int j)
    {
        if(p[i].ed<=p[j].st || p[j].ed<=p[i].st) return true;
        else return false;
    }
    
    char op[50];
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
        #endif
        int h1,m1,h2,m2,len;
        while(scanf("%d",&N)==1){
            init();
            all = 2*N;
            bool flag = true;
            for(int i=0;i<all;i+=2){
                scanf("%d:%d %d:%d %d",&h1,&m1,&h2,&m2,&len);
                p[i].st = h1*60+m1;
                p[i].ed = p[i].st + len;
                p[i^1].st = h2*60+m2-len;
                p[i^1].ed = p[i^1].st +len;
                if(p[i^1].ed - p[i].st<len) flag = false;
            }
    
            if(!flag){
                printf("NO
    ");
                continue;
            }
    
            int a1,a2,b1,b2;
            //[1-2N] 为去 ,[2N+1,4N]为不去
            for(int i=0;i<all;i+=2){
                a1 = i; a2 = i^1;
                for(int j= i+2 ;j< all ; j+=2){
                    b1 = j, b2 =j^1;
                    if(!check(a1,b1)){
                        AddEdge(a1,b2);
                        AddEdge(b1,a2);
                    }
                    if(!check(a1,b2)){
                        AddEdge(a1,b1);
                        AddEdge(b2,a2);
                    }
                    if(!check(a2,b1)){
                        AddEdge(a2,b2);
                        AddEdge(b1,a1);
                    }
                    if(!check(a2,b2)){
                        AddEdge(a2,b1);
                        AddEdge(b2,a1);
                    }
                }
            }
            solve();
        }
        return 0;
    }
    
    
    为了更好的明天
  • 相关阅读:
    Unix & Linux 教程学习_2
    Unix & Linux 教程学习
    再次测试一下markdown
    黑马程序员-OC练习作业
    黑马程序员-根据本地地址计算文本中有多少行的代码
    黑马程序员-OC常见结构体NSRange、NSPoint、NSSize、NSRect
    黑马程序员-OC内存管理的初步认识
    黑马程序员-OC的构造方法init以及自定义构造方法
    黑马程序员-OC的三大特性:封装、继承、多态
    黑马程序员-OC的类和对象的初步认识
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9606561.html
Copyright © 2020-2023  润新知