zoukankan      html  css  js  c++  java
  • 【CF1137C】 Museums Tour 拆点+缩点

    https://codeforc.es/contest/1137/problem/C

    # 题意

    给你n个点,每个点有k天博物馆开放时间的安排表。

    有m条单向道路,走过一条边需要一个晚上,经过后就是第二天的意思。

    问在无穷大的时间里,可以参观多少不同的博物馆。

    # 思路

    我们把每个点都拆出k个点,有单向边相连就从(u,i) -> (v, (i+1)%k)。

    缩点跑出DAG,然后DP出最多的博物馆参观数。

    这里就要考虑直接DP是否能行。假设有一条(u,i) -> (u, j)的边,由于没有自环且是单向边,所以一定可以通过循环,可以从(u,j)再走到(u,i),所以这两个点会缩在一起。

    由于这种做法缩点时递归很深,我是通过inline优化的,开O(3)好像也可以。

    #include <bits/stdc++.h>
    using namespace std;
    #define pb push_back
    #define fi first
    #define se second
    #define debug(x) cerr<<#x << " := " << x << endl;
    #define bug cerr<<"-----------------------"<<endl;
    #define FOR(a, b, c) for(int a = b; a <= c; ++ a)
     
    typedef long long ll;
    typedef long double ld;
    typedef pair<int, int> pii;
    typedef pair<ll, ll> pll;
     
     
    template<class T> void _R(T &x) { cin >> x; }
    void _R(int &x) { scanf("%d", &x); }
    void _R(ll &x) { scanf("%lld", &x); }
    void _R(double &x) { scanf("%lf", &x); }
    void _R(char &x) { scanf(" %c", &x); }
    void _R(char *x) { scanf("%s", x); }
    void R() {}
    template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
     
     
    template<typename T>
    inline T read(T&x){
        x=0;int f=0;char ch=getchar();
        while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x=f?-x:x;
    }
     
    const int inf = 0x3f3f3f3f;
     
    const int mod = 1e9+7;
     
    /**********showtime************/
                const int maxn = 5000009;
     
            //    vector<int>mp[maxn];
     
                int n,m,k;
                int getid(int x, int i) {
                    return (x - 1) * k + i + 1;
                }
     
                struct E{
                    int u,v;
                    int nxt;
                }edge[maxn];
     
                int gtot = 0, head[maxn];
     
                void addedge(int u, int v) {
                    edge[gtot].u = u;
                    edge[gtot].v = v;
                    edge[gtot].nxt = head[u];
                    head[u] = gtot++;
                }
     
                set <int> dpmp[maxn];
     
                char str[55];
                int dp[maxn],a[maxn];
                int belong[maxn], dfn[maxn] , low[maxn];
     
                bool vis[maxn];
                bool flag[maxn];
              //  int used[maxn];
     
                int tim, scc_cnt;
     
                //stack<int>st;
                queue<int>que;
                int st[5000009];
                int top = 0;
                inline void dfs(int u) {
                    dfn[u] = low[u] = ++tim;
     
    //                st.push(u);
                    st[++top] = u;
                    for(int i=head[u]; ~i; i=edge[i].nxt){
                        int v = edge[i].v;
                        if(!dfn[v]) dfs(v);
                        if(!belong[v]) low[u] = min(low[u], low[v]);
                    }
     
                    if(dfn[u] == low[u]) {
                        scc_cnt++;
                        int now;
                        while(true) {
                            now = st[top]; top--;
                            belong[now] = scc_cnt;
                            if(flag[now]) {
                                int id = (now - 1) / k + 1;
                                if(vis[id] == 0) {
                                    que.push(id);
                                    vis[id] = 1;
                                    a[scc_cnt]++;
                                }
                            }
                            if(now == u) break;
                        }
                        while(!que.empty()) {
                            int u = que.front(); que.pop();
                            vis[u] = 0;
                        }
                    }
                }
     
                int ans = 0;
                
                void cal(int s) {
                    queue<int>que;
                    dp[s] = a[s];
                    que.push(s);
                    ans = max(ans, a[s]);
     
                    while(!que.empty()) {
                        int u = que.front(); que.pop();
                        vis[u] = 0;
                        for(int v : dpmp[u]) {
                            dp[v] = max(dp[v], dp[u] + a[v]);
                            ans = max(ans, dp[v]);
                            if(vis[v] == 0) {
                                vis[v] = 1;
                                que.push(v);
                            }
                        }
                    }
                }
    int main(){
                memset(head, -1, sizeof(head));
                R(n, m, k);
                for(int i=1; i<=m; i++) {
                    int u,v;
                    scanf("%d%d", &u, &v);
                    for(int j=0; j<k; j++) {
                        addedge(getid(u, j), getid(v, (j+1)%k));
                    }
                }
     
                for(int i=1; i<=n; i++) {
                    scanf("%s", str);
                    for(int j=0; j<k; j++) {
                        flag[getid(i, j)] = (str[j] == '1');
                    }
                }
     
                for(int i=1; i<=n; i++){
                    for(int j=0; j<k; j++)
                        if(!dfn[getid(i, j)]) dfs(getid(i, j));
                }
     
                for(int i=0; i<gtot; i++){
                            int u = edge[i].u, v = edge[i].v;
                            if(belong[u] == belong[v]) continue;
                            dpmp[belong[u]].insert(belong[v]);                        
                }
     
                cal(belong[getid(1, 0)]);
     
                printf("%d
    ", ans);
                return 0;
    }
    View Code
  • 相关阅读:
    Cardiogram
    Increasing Speed Limits HDU
    Beaver Game CodeForces
    C++LeetCode:: Container With Most Water
    C++ leetcode::Reverse Integer
    C++ leetcode::ZigZag Conversion
    C++ leetcode Longest Palindromic Substring
    C++ leetcode Longest Substring Without Repeating Characters
    Faster RCNN
    C++ Leetcode Median of Two Sorted Arrays
  • 原文地址:https://www.cnblogs.com/ckxkexing/p/11186073.html
Copyright © 2011-2022 走看看