luogu1262 间谍网络

贿赂所有能贿赂的,如果还有人不被访问则显然是NO。
否则,必定为YES。强联通分量缩成一个DAG,若某点的入度为零,则答案要算上它的。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
struct Edge{
	int fro, too, nxt;
}edge[8005];
int n, p, uu, vv, scc, w[3005], cnt, hea[3005], dfn[3005], loo[3005], ind, sta[3005], din, r, ans;
int minn[3005], bel[3005], dge[3005];
bool ins[3005];
void add_edge(int fro, int too){
	edge[++cnt].nxt = hea[fro];
	edge[cnt].fro = fro;
	edge[cnt].too = too;
	hea[fro] = cnt;
}
void dfs(int u){
	ins[u] = true;
	for(int i=hea[u]; i; i=edge[i].nxt){
		int t=edge[i].too;
		if(!ins[t])	dfs(t);
	}
}
void tarjan(int u){
	sta[++din] = u;
	ins[u] = true;
	dfn[u] = loo[u] = ++ind;
	for(int i=hea[u]; i; i=edge[i].nxt){
		int t=edge[i].too;
		if(!dfn[t]){
			tarjan(t);
			loo[u] = min(loo[u], loo[t]);
		}
		else if(ins[t])	loo[u] = min(loo[u], dfn[t]);
	}
	int j;
	if(dfn[u]==loo[u]){
		scc++;
		do{
			j = sta[din--];
			bel[j] = scc;
			ins[j] = false;
			minn[scc] = min(minn[scc], w[j]);
		}while(dfn[j]!=dfn[u]);
	}
}
int main(){
	cin>>n>>p;
	memset(w, 0x3f, sizeof(w));
	memset(minn, 0x3f, sizeof(minn));
	for(int i=1; i<=p; i++)	scanf("%d", &uu), scanf("%d", &w[uu]);
	cin>>r;
	for(int i=1; i<=r; i++){
		scanf("%d %d", &uu, &vv);
		add_edge(uu, vv);
	}
	for(int i=1; i<=n; i++)
		if(w[i]!=0x3f3f3f3f && !ins[i])
			dfs(i);
	for(int i=1; i<=n; i++)
		if(!ins[i]){
			cout<<"NO
"<<i;
			return 0;
		}
	memset(ins, 0, sizeof(ins));
	for(int i=1; i<=n; i++)
		if(!dfn[i])
			tarjan(i);	
	for(int i=1; i<=cnt; i++)
		if(bel[edge[i].fro]!=bel[edge[i].too])
			dge[bel[edge[i].too]]++;
	for(int i=1; i<=scc; i++){
		if(!dge[i])
			ans += minn[i];
	}
	cout<<"YES
"<<ans;
	return 0;
}
原文地址:https://www.cnblogs.com/poorpool/p/7943382.html