洛谷 P1262

题目链接: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);
}
posted @ 2020-09-01 14:14  Aliemo  阅读(95)  评论(0编辑  收藏  举报