cf949C Data Center Maintenance

题意:
某土豪公司建立了n个数据中心,把m份资料每份在其中的两个数据中心备份。 每个数据中心在一天h个小时当中有一个小时需要维护,此时不提供资料下载服务。 现在土豪公司想要将其中若干个数据中心的维护时间向后推迟一小时,并要求一天中任意时刻每份资料都可以被下载,问最少选取多少个数据中心维护。
输入 第一行n,m,h,见题目描述 第二行n个整数,维护时间 接下来m行,每行两个整数,存相同资料的一对中心
输出 第一行 必须推迟数 第二行 分别是哪些中心

抽象成点后 用边表示冲突
和前几天做的一个 POI 题方法类似。我们考虑把数据中心抽象成点。对于一个客户的两组数据,如果维护时间相隔很久那么两个数据间不会有冲突,如果是相邻的,我们把时间轴在前面的点向后面的点连一条边。表示若选取这个点,则与所指向的点冲突。
如果图中出现了 强连通分量。则必须选取整个强连通分量,故缩点。
缩点后所建成新图是一个 DAG D A G 有向无环图。我们只要选取没有出度中答案最优的点即可。

#include<bits/stdc++.h>
using namespace std;

const int MAXN=1e5+5;

struct edge{
    int to,next;
}e[MAXN<<1],ec[MAXN<<1];

int head[MAXN],cnt=0,headc[MAXN],cnt2=0,indegree[MAXN];

inline void add(int u,int v){
    e[++cnt]=(edge){v,head[u]},head[u]=cnt;
}

inline void addc(int u,int v){
    ec[++cnt2]=(edge){v,headc[u]},headc[u]=cnt2,indegree[u]++;
}

int dfn[MAXN],low[MAXN],belong[MAXN],tot=0,colorsize[MAXN],tim=0;
int sta[MAXN],top=0;
bool insta[MAXN];

vector<int>vec[MAXN];

void tarjan(int u){
    sta[++top]=u;
    insta[u]=1;
    dfn[u]=low[u]=++tim;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(insta[v]&&dfn[v]<low[u])low[u]=dfn[v];
    }
    if(dfn[u]==low[u]){
        int tem=0;++tot;
        while(tem!=u){
            tem=sta[top--];
            vec[tot].push_back(tem);
            insta[tem]=0;
            belong[tem]=tot;
            colorsize[tot]++;
        }
    }
}

int a[MAXN],n,m,h;

int main(){
    scanf("%d%d%d",&n,&m,&h);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        if(a[x]>a[y])swap(x,y);
        if(a[y]-a[x]==1)add(x,y);
        if(a[x]==0&&(a[y]==h-1))add(y,x);
        //if(abs(a[x]-a[y])==1||((a[x]==h-1)&&(!a[y])))add(x,y),cout<<x<<" sas "<<y<<endl;
    }
    for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
    for(int u=1;u<=n;u++){
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(belong[v]!=belong[u])addc(belong[u],belong[v]);
        }
    }
    int ans=2e9,which;
    for(int i=1;i<=tot;i++){
        if(!indegree[i]){
            if(colorsize[i]<ans)ans=colorsize[i],which=i;
        }
    }
    printf("%d\n",ans);
    for(int i=0;i<vec[which].size();i++){
        printf("%d ",vec[which][i]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值