zoukankan      html  css  js  c++  java
  • poj 3683 Priest John's Busiest Day 夜

    http://poj.org/problem?id=3683

    标准的2-sat 而且是需要输出路径的 

    一直纠结 缩点后建反向图 再利用拓扑排序那一点到底是怎么弄的  原来是自己的拓扑排序没学好 晕

    还有刚开始学邻接表的时候一直用动态的 就是没加一条边都要申请一个 new node

    没想到这次就超时了  因为边太多了  改成静态的直接100ms+  差距太大了 以后不敢再用动态的了

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<string>
    #include<vector>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #define LL long long
    
    using namespace std;
    
    const int N=2005;
    vector<int>ve[2005];//保存环
    int head1[N],I1;
    int head2[N],I2;
    struct ss1
    {
        int j,next;
    }side1[N*1000];//初始邻接表
    struct ss2
    {
        int j,next;
    }side2[N*1000];//缩点后 反向邻接表
    struct T
    {
        int st,et;
    }setime[N];
    int dfn[N];
    int low[N];
    bool in[N];
    bool visited[N];
    int deep;
    int f[N];
    stack<int>str;
    queue<int>qt;
    int num[N];//拓扑排序计数
    int sele[N];//选择 0 为未选 1为选 -1为不选
    void build(int i,int j)
    {
        side1[I1].j=j;
        side1[I1].next=head1[i];
        head1[i]=I1++;
    }
    void rebuild(int i,int j)
    {
        side2[I2].j=j;
        side2[I2].next=head2[i];
        head2[i]=I2++;
    }
    void Tarjan(int x)//判环 缩点
    {
        visited[x]=true;
        str.push(x);
        in[x]=true;
        dfn[x]=low[x]=deep++;
        int t=head1[x];
        while(t!=-1)
        {
            int k=side1[t].j;
            if(visited[k]==false)
            {
                Tarjan(k);
                low[x]=min(low[x],low[k]);
            }else if(in[k]==true)
            {
                low[x]=min(low[x],dfn[k]);
            }
            t=side1[t].next;
        }
        if(low[x]==dfn[x])
        {
            while(str.top()!=x)
            {
                int k=str.top();
                str.pop();
                in[k]=false;
                f[k]=x;
                ve[x].push_back(k);
            }
            int k=str.top();
            str.pop();
            in[k]=false;
            f[k]=x;
        }
    
    }
    bool same(int i,int j)//时间是否冲突
    {
        if(setime[i].et<=setime[j].st)
        return false;
        if(setime[j].et<=setime[i].st)
        return false;
        return true;
    }
    void fsearch(int x)//反向建邻接表 只建缩点 
    {
        int t=head1[x];
        while(t!=-1)
        {
            int k=side1[t].j;
            if(f[x]!=f[k])
            {
                rebuild(f[k],f[x]);
                ++num[f[x]];//拓扑排序 计数
            }
            t=side1[t].next;
        }
    }
    void subside(int x)//拓扑中 用掉一个边 将它指向的点的计数减一 为0的话 入队列 
    {
        int t=head2[x];
        while(t!=-1)
        {
            --num[side2[t].j];
            if(num[side2[t].j]==0)
            qt.push(side2[t].j);
            t=side2[t].next;
        }
    }
    void color(int k,int n)//将一个环内的点 然成相同颜色
    {
        int l1=k;
        int l2=(k<n)?k+n:k-n;
        l1=f[l1];l2=f[l2];
        sele[l1]=1;
        for(unsigned int i=0;i<ve[l1].size();++i)
        sele[ve[l1][i]]=1;
        sele[l2]=-1;
        for(unsigned int i=0;i<ve[l2].size();++i)
        sele[ve[l2][i]]=-1;
    }
    void print(int i)//输出
    {
        int t1=setime[i].st;
        int t2=setime[i].et;
        printf("%02d:%02d %02d:%02d\n",t1/60,t1%60,t2/60,t2%60);
    }
    int main()
    {
        //freopen("data.txt","r",stdin);
        int n;
        while(scanf("%d",&n)!=EOF)
        {
    
            int l1,l2,k1,k2,d;
            char c1,c2;
            memset(head1,-1,sizeof(head1));
            I1=0;
            for(int i=0;i<n;++i)
            {
                scanf("%d%c%d %d%c%d %d",&l1,&c1,&l2,&k1,&c2,&k2,&d);
                setime[i].st=l1*60+l2;
                setime[i].et=l1*60+l2+d;
                setime[i+n].et=k1*60+k2;
                setime[i+n].st=k1*60+k2-d;
                for(int j=0;j<i;++j)
                {
                    if(same(j,i))//判断是否冲突
                    {
                        build(j,i+n);build(i,j+n);
                    }
                    if(same(j+n,i))
                    {
                        build(j+n,i+n);build(i,j);
                    }
                    if(same(j,i+n))
                    {
                        build(j,i);build(i+n,j+n);
                    }
                    if(same(j+n,i+n))
                    {
                        build(j+n,i);build(i+n,j);
                    }
                }
            }
            while(!str.empty())
            str.pop();
            memset(dfn,-1,sizeof(dfn));
            memset(low,-1,sizeof(low));
            memset(in,false,sizeof(in));
            memset(visited,false,sizeof(visited));
            for(int i=0;i<2*n;++i)
            f[i]=i;
            deep=0;
            for(int i=0;i<n;++i)
            ve[i].clear();
            int l;
            for(l=0;l<n;++l)
            {
                if(visited[l]==false)
                Tarjan(l);
                if(f[l]==f[l+n])
                break;
            }
            if(l<n)
            printf("NO\n");
            else
            {
                printf("YES\n");
                memset(head2,-1,sizeof(head2));
                I2=0;
                for(int i=0;i<2*n;++i)
                fsearch(i);//重新建反向图
                for(int i=0;i<2*n;++i)
                if(f[i]==i&&num[i]==0)
                qt.push(i);//拓扑后为0的进队列
                memset(sele,0,sizeof(sele));
                while(!qt.empty())
                {
                    int k=qt.front();
                    qt.pop();
                    if(sele[k]==0)//为染色的染色
                    color(k,n);
                    subside(k);
                }
                for(int i=0;i<n;++i)
                {
                    if(sele[i]==1)
                    print(i);
                    else
                    print(i+n);
                }
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    JavaScript数组迭代方法
    Ant Design Mobile RN中Toast不起作用的原因【坑篇】
    解决vsCode终端不能运行yarn脚本
    k8s——Service和Ingress
    Prometheus学习
    k8s——pod控制器
    k8s——管理pod资源对象
    k8s——资源管理基础
    docker学习
    k8s学习——Helm入门及使用
  • 原文地址:https://www.cnblogs.com/liulangye/p/2641147.html
Copyright © 2011-2022 走看看