• Codeforces 949C(Data Center Maintenance,Tarjan缩点)


    难度系数:1900 graphs

    题意:有 n 个银行,m 个客户,每个客户都把自己的资料放在 2 个银行,一天总共有 h 小时,每个银行每天都要维护一小时,这一小时内银行无法工作,但是这一小时客户仍然可以在另一个银行提取资料,于是客户就可以一天 h 小时随时提取资料。现在要选择 k 个银行进行实验,每个进行实验的银行,它每天的维护时间都推迟一小时,如果原来的维护时间是 h−1 时,进行实验后银行的维护时间就为 0 时。问最少选择几个银行(至少一个)进行实验,才能仍然保证每一个客户随时都能提取到资料。

    输入:第一行为 3 个整数n,m,h (2≤n≤105,1≤m≤1e5,2≤h≤1e5),第二行为 nn 个整数 u1,u2,⋯,un (0≤ui<h)表示第 i 个银行一天内需要维护的时间点。接下去 m行每行两个整数 ci,1,ci,2 (1≤ci,1,ci,2≤n),表示第 i 个客户把资料存放在第 ci,1 和第 ci,2 个银行。数据保证最初每一个客户都可以在一天的任意时刻取得资料。

    解法:其实想想也能知道转化成图论关系,但是怎么建边呢?我们可以知道如果(p[u]+1)%h==p[v],就能在u和v之间建立一个单向边,add(u,v);同样,如果(p[v]+1)%h==p[u],就能在v和u之间建立一个单向边,add(v,u)。记住建边的时候不要用 else if,因为有一组数据卡的条件是回路只有2个点...既然知道了建边的关系了,那么我们就可以利用Tarjan强联通的缩点方法把它缩成id[i],这个时候统计一下每个id[i]的outdeg有几个;我们寻找答案的方法是:1~n中,outdeg[id[i]]为0,且num[id[i]]最小。那么其实这个问题说到这个地步也算是比较简单了。感觉想想还是挺容易的,就是坑点有点多吧。。。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define endl '
    '
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int INF=0x3f3f3f3f;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    const int mod=1e9+7;
    const int maxn=1e5+5;
    int tot,head[maxn];
    struct E{
        int to,next;
    }edge[maxn<<1];
    void add(int u,int v){
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    int n,m,h,p[maxn],dfn[maxn],low[maxn],vis[maxn],id[maxn],num[maxn],tott,cnt=0;
    stack<int> s;
    void tarjan(int x){
        low[x]=dfn[x]=++tott;
        s.push(x);vis[x]=1;
        for(int i=head[x];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(!dfn[v]){
                tarjan(v);
                low[x]=min(low[x],low[v]);
            }
            else if(vis[v]){
                low[x]=min(low[x],dfn[v]);
            }
        }
        if(low[x]==dfn[x]){
            cnt++;
            while(1){
                int now=s.top();s.pop();
                vis[now]=0;
                id[now]=cnt;
                num[cnt]+=1;
                if(now==x) break;
            }
        }
    }
    int out[maxn];vector<int> G[maxn];
    int main(){
        cin>>n>>m>>h;mem(head,-1);
        rep(i,1,n) cin>>p[i];
        while(m--){
            int u,v;cin>>u>>v;
            if((p[u]+1)%h==p[v]) add(u,v);
            if((p[v]+1)%h==p[u]) add(v,u);
        }
        rep(i,1,n){
            if(!dfn[i]) tarjan(i);
        }
        for(int i=1;i<=n;i++){
            for(int j=head[i];j!=-1;j=edge[j].next){
                if(id[i]!=id[edge[j].to]){
                    G[id[i]].push_back(id[edge[j].to]);
                    out[id[i]]+=1;
                }
            }
        }
        int ans=INF,cur;
        for(int i=1;i<=cnt;i++){
            if(out[i]==0){
                ans=min(ans,num[i]);
                if(num[i]==ans) cur=i;
            }
        }
        vector<int> vec;
        for(int i=1;i<=n;i++){
            if(id[i]==cur){
                vec.push_back(i);
            }
        }    
        cout<<ans<<endl;
        for(int i=0;i<vec.size();i++){
            cout<<vec[i]<<" ";
        }
        puts("");
    }
    View Code

     

  • 相关阅读:
    网络对抗技术 20192424 Exp7 网络欺诈防范
    CAN帧格式解析
    C语言复杂的指针
    堆栈段的用途
    uniapp益智五子棋小程序
    穿山甲GroMore广告—(Banner广告)——Android_Unity广告系列文章03
    穿山甲GroMore广告(概览)——Unity游戏接入广告Android篇02
    穿山甲GroMore广告—(信息流广告)——Android_Unity广告系列文章04
    使用Android发布Unity无法破解的问题
    Json Number Format 异常 Expected an int but was 2168520652 at line 1 column 325
  • 原文地址:https://www.cnblogs.com/Anonytt/p/12899840.html
Copyright © 2020-2023  润新知