zoukankan      html  css  js  c++  java
  • Codeforces 1137C Museums Tour (强连通分量, DP)

    题意和思路看这篇博客就行了:https://www.cnblogs.com/cjyyb/p/10507937.html

    有个问题需要注意:对于每个scc,只需要考虑进入这个scc的时间即可,其实和从哪个点进没有关系,因为scc内每个点都可以互相到达,所以只需记录时间就囊括了所有的情况,比如时间3从1号点进和时间4从2号点进是等价的,这也是为什么可以随便选择一颗生成树的原因。对于scc的出边,边的长度是val[u] + val[v] - 1,因为假设从scc x的根 到点scc y的点v,时间是val[u] + 1,而scc y的根到v的距离是val[v],所以要求原装态需要减去这个。当然,这个边需要对两个scc的gcd的gcd取模,以判断从这条边到下一条边可以到达的状态。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 100010;
    
    int head[maxn], Next[maxn * 2], ver[maxn * 2], tot;
    int heade[maxn], Nexte[maxn * 2 * 50], edgee[maxn * 2 * 50], vere[maxn * 2 * 50], tote, cnt;
    int n, m, D, GCD, g[maxn], f[maxn][51], pre[maxn][51], deg[maxn], val[maxn], c[maxn];
    int dfn[maxn], low[maxn], num, top, Stack[maxn];
    char v[maxn][51];
    bool vis[maxn], ins[maxn];
    vector<int> scc[maxn];
    void add(int x, int y) {
    	ver[++tot] = y;Next[tot] = head[x];head[x] = tot;
    }
    
    void adde(int x, int y, int z) {
    	vere[++tote] = y, edgee[tote] = z, Nexte[tote] = heade[x], heade[x] = tote, deg[y]++;
    }
    
    void solve(int x, int p) {
    	val[x] = p, vis[x] = 1;
    	for (int i = head[x]; i; i = Next[i]) {
    		int y = ver[i];
    		if(c[y] != cnt) continue;
    		if(!vis[y]) solve(y, p + 1);
    		else GCD = __gcd(GCD, abs(p + 1 - val[y]));
    	}
    }
    
    void tarjan(int x) {
    	dfn[x] = low[x] = ++num;
    	Stack[++top] = x, ins[x] = 1;
    	for (int i = head[x]; i; i = Next[i]) {
    		if (!dfn[ver[i]]) {
    			tarjan(ver[i]);
    			low[x] = min(low[x], low[ver[i]]); 
    		} else if (ins[ver[i]])
    			low[x] = min(low[x], dfn[ver[i]]);
    	}
    	if (dfn[x] == low[x]) {
    		cnt++;
    		int y;
    		do {
    			y = Stack[top--], ins[y] = 0;
    			c[y] = cnt, scc[cnt].push_back(y);
    		} while(x != y);
    		GCD = D, solve(x, 0); g[cnt] = GCD;
    		for (int i = 0; i < GCD; i++)
    			for (int j = 0; j < scc[cnt].size(); j++) {
    				for (int k = i; k < D; k += GCD)
    					if(v[scc[cnt][j]][k] == '1') {
    						v[scc[cnt][j]][i] = '1';
    						break;
    					}
    			}
    		for (int i = 0; i < GCD; i++)
    			for (int j = 0; j < scc[cnt].size(); j++) {
    				if(v[scc[cnt][j]][(val[scc[cnt][j]] + i) % GCD] == '1')
    					pre[cnt][i]++;
    			}
    	}
    }
    
    void dp(void) {
    	int ans = 0;
    	memset(f, -0x3f, sizeof(f));
    	f[c[1]][0] = pre[c[1]][0];
    	queue<int> q;
    	for (int i = 1; i <= cnt; i++) {
    		if (!deg[i])
    			q.push(i);
    	}
    	while(!q.empty()) {
    		int x = q.front();
    		q.pop();
    		for (int i = heade[x]; i; i = Nexte[i]) {
    			int y = vere[i];
    			deg[y]--;
    			if(deg[y] == 0)
    				q.push(y);
    		}
    		for (int i = heade[x]; i; i = Nexte[i]) {
    			for (int j = 0; j < D; j++) {
    				int y = vere[i], z = edgee[i];
    				f[y][(z + j) % D] = max(f[y][(z + j) % D], f[x][j] + pre[y][(z + j) % g[y]]);
    			}
    		}
    		for (int i = 0; i < D; i++)
    			ans = max(ans, f[x][i]);
    	}
    	printf("%d
    ", ans);
    }
    
    int main() {
    	int x, y;
    	scanf("%d%d%d", &n, &m, &D);
    	for (int i = 1; i <= m; i++) {
    		scanf("%d%d", &x, &y);
    		add(x, y);
    	}
    	for (int i = 1; i <= n; i++)
    		scanf("%s", v[i]);
    	for (int i = 1; i <= n; i++) {
    		if(!dfn[i])
    			tarjan(i);
    	}
    	for (int j = 1; j <= n; j++)
    		for (int i = head[j]; i; i = Next[i]) {
    			int y = ver[i];
    			if(c[j] == c[y]) continue;
    			int dd = __gcd(g[c[j]], g[c[y]]);
    			int d = (val[j] - val[y] + 1 + D) % D;
    			for (int k = d % dd; k < D; k += dd) {
    				adde(c[j], c[y], k);
    			}
    		}
    	dp();
    } 
    

      

  • 相关阅读:
    CodeForces-1100C NN and the Optical Illusion 简单数学
    HDU-3038 How Many Answers Are Wrong 并查集
    POJ-1321 棋盘问题 DFS
    POJ-1651 Multiplication Puzzle 区间DP
    HDU-2037 今年暑假不AC 贪心
    排序算法的总结
    UVa-679 Dropping Balls 二叉树
    Coursera机器学习——Recommender System测验
    页面置换算法及例题
    这篇最新MySQL面试题请查收
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/10562413.html
Copyright © 2011-2022 走看看