基本上都是板子, 还没做完
loj
10091 受欢迎的牛
缩点后出度为$ 0 $的点就是欢迎的牛,超过一个点则不存在
#include <bits/stdc++.h> using namespace std; const int N = 10000 + 50; const int M = 50000 + 50; struct node { int next, to; } edge[M]; int cnt, head[N]; inline void add(int from, int to) { edge[++cnt] = (node){ head[from], to }, head[from] = cnt; } int n, m, col, top, tot; int cd[N], color[N], Stack[N], low[N], dfn[N], visited[N], sum[N]; // namespace newgraph{ // int cnt, head[N]; // struct node{ int next, to; }edge[M]; // inline void add(int from, int to) { edge[++cnt] = (node){head[from], to}, head[from] = cnt;} } //} void tarjan(int u) { Stack[++top] = u, dfn[u] = low[u] = ++tot, visited[u] = 1; for (int i = head[u]; i; i = edge[i].next) { int v = edge[i].to; if (!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]); else if (visited[v]) low[u] = min(low[u], dfn[v]); } if (low[u] == dfn[u]) { color[u] = ++col, sum[col]++, visited[u] = 0; while (Stack[top] != u) { color[Stack[top]] = col; sum[col]++; visited[Stack[top--]] = 0; } top--; } } int main() { cin >> n >> m; for (int i = 1, u, v; i <= m; i++) scanf("%d%d", &u, &v), add(u, v); for (int i = 1; i <= n; i++) if (!dfn[i]) tarjan(i); for (int i = 1; i <= n; i++) for (int j = head[i]; j; j = edge[j].next) if (color[i] != color[edge[j].to]) cd[color[i]]++; int ans = 0, sky; for (int i = 1; i <= col; i++) if (!cd[i]) ans++, sky = i; if (ans == 1) cout << sum[sky]; else puts("0"); return 0; }
10093 网络协议
缩点后入度为零的点为第一问,$ max(rd, cd) $ 为第二问。
原因大概就是 形成的 $ DAG $ , 是由几条单向的链合成的, 每条链都要收尾连成环, 故取max
10094 消息的传递
模板
#include <bits/stdc++.h> using namespace std; const int N = 1100; const int M = N * N; struct node { int next, to; } edge[M]; int cnt, head[N]; inline void add(int from, int to) { edge[++cnt] = (node){ head[from], to }, head[from] = cnt; } int dfn[N], low[N], visited[N], Stack[N], color[N], rd[N]; int tot, top, col; int n, ans; void tarjan(int u) { dfn[u] = low[u] = ++tot, Stack[++top] = u, visited[u] = 1; for (int i = head[u]; i; i = edge[i].next) { int v = edge[i].to; if (!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]); else if (visited[v]) low[u] = min(low[u], dfn[v]); } if (low[u] == dfn[u]) { color[u] = ++col, visited[u] = 0; while (Stack[top] != u) { color[Stack[top]] = col; visited[Stack[top--]] = 0; } top--; } } int main() { cin >> n; for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { int x; scanf("%d", &x); if (x) add(i, j); } } for (int i = 1; i <= n; i++) if (!dfn[i]) tarjan(i); for (int i = 1; i <= n; i++) for (int j = head[i]; j; j = edge[j].next) if (color[i] != color[edge[j].to]) rd[color[edge[j].to]]++; for (int i = 1; i <= col; i++) if (!rd[i]) ans++; cout << ans; return 0; }
10095 间谍网络
缩点后入度为零的点才可以收买,但判断是否有解时神经病了,看的题解。
#include <bits/stdc++.h> using namespace std; const int N = 3e3 + 50; const int M = 8e3 + 50; const int inf = 1e9 + 7; struct node { int next, to; } edge[M]; int cnt, head[N]; inline void add(int from, int to) { edge[++cnt] = (node){ head[from], to }, head[from] = cnt; } int n, p, r; int cost[N], bribe[N], dfn[N], low[N], color[N], Stack[N], visited[N], rd[N]; int tot, top, col; void tarjan(int u) { Stack[++top] = u, low[u] = dfn[u] = ++tot, visited[u] = 1; for (int i = head[u]; i; i = edge[i].next) { int v = edge[i].to; if (!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]); else if (visited[v]) low[u] = min(low[u], dfn[v]); } if (low[u] == dfn[u]) { color[u] = ++col, visited[u] = 0; bribe[col] = cost[u]; while (Stack[top] != u) { color[Stack[top]] = col; bribe[col] = min(bribe[col], cost[Stack[top]]); visited[Stack[top--]] = 0; } top--; } } int main() { cin >> n >> p; for (int i = 1; i <= n; i++) cost[i] = bribe[i] = inf; for (int i = 1; i <= p; i++) { int a, b; scanf("%d%d", &a, &b); cost[a] = b; } cin >> r; for (int i = 1; i <= r; i++) { int u, v; scanf("%d%d", &u, &v); add(u, v); } for (int i = 1; i <= n; i++) if (!dfn[i] && cost[i] != inf) tarjan(i); for (int i = 1; i <= n; i++) if (!dfn[i]) return printf("NO\n%d", i), 0; for (int i = 1; i <= n; i++) for (int j = head[i]; j; j = edge[j].next) if (color[i] != color[edge[j].to]) rd[color[edge[j].to]]++; int ans = 0; for (int i = 1; i <= col; i++) if (!rd[i]) ans += bribe[i]; cout << "YES" << '\n' << ans; return 0; }
10096 抢掠计划
缩点,建造新图,跑最长路,中途记录答案
#include<bits/stdc++.h> using namespace std; const int N = 5e5+50; const int M = 5e5+50; struct node{ int next, to; }edge[M]; int cnt, head[N]; inline void add(int from, int to) { edge[++cnt] = (node) {head[from], to}, head[from] = cnt; } int dfn[N], low[N], visited[N], Stack[N], color[N], rd[N], sum[N], cost[N], bar[N], new_bar[N]; int tot, top, col; int n, m, ans, s, p; void tarjan(int u) { dfn[u] = low[u] = ++tot, Stack[++top] = u, visited[u] = 1; for(int i = head[u]; i; i = edge[i].next) { int v = edge[i].to; if(!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]); else if(visited[v]) low[u] = min(low[u], dfn[v]); } if(low[u] == dfn[u]) { color[u] = ++col, visited[u] = 0; sum[col] = cost[u], new_bar[col] = bar[u]; while(Stack[top] != u) { int t = Stack[top]; color[t] = col; sum[col] += cost[t]; visited[t] = 0; new_bar[col] += bar[t]; top--; } top--; } } namespace new_graph{ struct node{ int next, to; }edge[M]; int cnt, head[N]; inline void add(int from, int to) { edge[++cnt] = (node) {head[from], to}, head[from] = cnt; } int dis[N]; queue<int> q; void spfa() { q.push(color[s]); dis[color[s]] = sum[color[s]]; while(!q.empty()) { int u = q.front(); q.pop(); for(int i = head[u]; i; i = edge[i].next) { int v = edge[i].to; if(dis[v] < dis[u] + sum[v]) { dis[v] = dis[u] + sum[v]; if(new_bar[v]) ans = max(ans, dis[v]); q.push(v); } } } } } int main() { cin>>n>>m; for(int i = 1, a, b; i <= m; i++) scanf("%d%d", &a, &b), add(a, b); for(int i = 1; i <= n; i++) scanf("%d",&cost[i]); cin>>s>>p; for(int i = 1, x; i <= p; i++) scanf("%d",&x), bar[x] = 1; for(int i = 1; i <= n; i++) if(!dfn[i]) tarjan(i); for(int i = 1; i <= n; i++) for(int j = head[i]; j; j = edge[j].next) if(color[i] != color[edge[j].to]) new_graph::add(color[i], color[edge[j].to]); new_graph::spfa(); cout<<ans; return 0; }
来源:https://www.cnblogs.com/skkyk/p/12181894.html