标签:lis str 消息 nod graph else dag oid sky
基本上都是板子, 还没做完
缩点后出度为$ 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;
}
缩点后入度为零的点为第一问,$ max(rd, cd) $ 为第二问。
原因大概就是 形成的 $ DAG $ , 是由几条单向的链合成的, 每条链都要收尾连成环, 故取max
模板
#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;
}
缩点后入度为零的点才可以收买,但判断是否有解时神经病了,看的题解。
#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;
}
缩点,建造新图,跑最长路,中途记录答案
#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;
}
标签:lis str 消息 nod graph else dag oid sky
原文地址:https://www.cnblogs.com/skkyk/p/12181894.html