题目链接:P1262 间谍网络
题目大意
开局一张有向图通关靠贿赂
题目中给了一张有向图,你可以选择几个有点权的开始走,如果不能遍历完,那就输出NO,然后输出不能遍历到的最小编号,反之,输出YES,和你选的几个点的和最小的值
solution
我们发现在一个环中可以互相得到对方的情报,然后我们取环中的最小值,然后再缩个点,我们这道题就做完了,从入度为0的点开始跑,然后跑不到就输出NO,反之加和就ok
Code:
/**
* Author: Alieme
* Data: 2020.9.1
* Problem: Luogu P1262
* Time: O()
*/
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#define ll long long
#define rr register
#define inf 1e9
#define MAXN 100010
using namespace std;
inline int read() {
int s = 0, f = 0;
char ch = getchar();
while (!isdigit(ch)) f |= ch == '-', ch = getchar();
while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
return f ? -s : s;
}
void print(int x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) print(x / 10);
putchar(x % 10 + 48);
}
struct Edge {
int nxt;
int to;
Edge() {}
Edge(int Nxt, int To) {nxt = Nxt, to = To;}
}e[MAXN];
int n, p, r, tot, ans, top, tp, cnt;
int a[MAXN], head[MAXN], dfn[MAXN], low[MAXN], sum[MAXN], stack[MAXN], belong[MAXN], rd[MAXN], siz[MAXN], money[MAXN];
bool vis[MAXN];
inline void add(int from, int to) {
e[++tot] = Edge(head[from], to);
head[from] = tot;
}
void Tarjan(int x) {
dfn[x] = low[x] = ++tp;
vis[x] = 1;
stack[++top] = x;
for (rr int i = head[x]; i; i = e[i].nxt) {
int to = e[i].to;
if (!dfn[to]) {
Tarjan(to);
low[x] = min(low[x], low[to]);
}
else if (vis[to]) low[x] = min(low[x], dfn[to]);
}
if (low[x] == dfn[x]) {
cnt++;
while (stack[top + 1] != x) {
belong[stack[top]] = cnt;
vis[stack[top]] = 0;
siz[cnt]++;
sum[cnt] = min(sum[cnt], money[stack[top]]);
top--;
}
}
}
signed main() {
n = read();
p = read();
for (rr int i = 1; i <= n; i++) money[i] = inf;
for (rr int i = 1; i <= n; i++) sum[i] = inf;
for (rr int i = 1; i <= p; i++) {
int u = read();
money[u] = read();
}
r = read();
for (rr int i = 1; i <= r; i++) {
int u = read(), v = read();
add(u, v);
}
for (rr int i = 1; i <= n; i++)
if (!dfn[i] && money[i] != inf)
Tarjan(i);
for (rr int i = 1; i <= n; i++)
if (!dfn[i]) {
puts("NO");
print(i);
return 0;
}
for (rr int i = 1; i <= n; i++)
for (rr int j = head[i]; j; j = e[j].nxt)
if (belong[i] != belong[e[j].to])
rd[belong[e[j].to]]++;
puts("YES");
for (rr int i = 1; i <= cnt; i++)
if (!rd[i])
ans += sum[i];
print(ans);
}