P1262 间谍网络

Sol

注意到如果多个间谍在一个 scc 内,那么显然只需要买通一个就行了,那么缩点之后的权值就是缩点前里面点权值的最小值。

然后求出入度为 \(0\) 的点的权值之和即可(缩点以后的)。

Code

#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define eb emplace_back
#define pf push_front
#define desktop "C:\\Users\\MPC\\Desktop\\"
#define IOS ios :: sync_with_stdio (false),cin.tie (0),cout.tie (0)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair <int,int> PII;
const int dx[] = {1,0,-1,0},dy[] = {0,-1,0,1};
template <typename T1,typename T2> bool tomax (T1 &x,T2 y) {
	if (y > x) return x = y,true;
	return false;
}
template <typename T1,typename T2> bool tomin (T1 &x,T2 y) {
	if (y < x) return x = y,true;
	return false;
}
LL power (LL a,LL b,LL p) {
	LL ans = 1;
	while (b) {
		if (b & 1) ans = ans * a % p;
		a = a * a % p;
		b >>= 1;
	}
	return ans;
}
int fastio = (IOS,0);
#define endl '\n'
#define puts(s) cout << (s) << endl
const int N = 3010,INF = 0x3f3f3f3f;
int n,m,k;
int a[N],w[N];
vector <int> g[N];
int dfn[N],low[N],timestamp;
int stk[N],top;
bool in_stk[N];
int id[N],scc_cnt;
int in_deg[N];
void tarjan (int u) {
	dfn[u] = low[u] = ++timestamp;
	stk[++top] = u;
	in_stk[u] = 1;
	for (int v : g[u]) {
		if (!dfn[v]) {
			tarjan (v);
			tomin (low[u],low[v]);
		}
		else if (in_stk[v]) tomin (low[u],dfn[v]);
	}
	if (dfn[u] == low[u]) {
		scc_cnt++;
		do {
			id[stk[top]] = scc_cnt;
			tomin (w[scc_cnt],a[stk[top]]);
			in_stk[stk[top]] = 0;
		}
		while (stk[top--] != u) ;
	}
}
void mian () {
	cin >> n;
	memset (a,0x3f,sizeof (a));
	memset (w,0x3f,sizeof (w));
	cin >> k;
	while (k--) {
		int x,y;
		cin >> x >> y;
		a[x] = y;
	}
	cin >> m;
	while (m--) {
		int a,b;
		cin >> a >> b;
		g[a].pb (b);
	}
	for (int i = 1;i <= n;i++) {
		if (!dfn[i] && a[i] != INF) tarjan (i);
	}
	for (int i = 1;i <= n;i++) {
		if (!dfn[i]) {
			puts ("NO");
			cout << i << endl;
			return ;
		}
	}
	puts ("YES");
	for (int i = 1;i <= n;i++) {
		for (int j : g[i]) {
			if (id[i] != id[j]) in_deg[id[j]]++;
		}
	}
	LL ans = 0;
	for (int i = 1;i <= scc_cnt;i++) if (!in_deg[i]) ans += w[i];
	cout << ans << endl;
}
int main () {
	int T = 1;
	// cin >> T;
	while (T--) mian ();
	return 0;
}
posted @ 2025-05-14 20:15  incra  阅读(6)  评论(0)    收藏  举报