洛谷P1262间谍网络

题目

我们首先考虑该题没有环应该怎么做,因为没有环所以是一个DAG,因此直接加上入度为0的罪犯,而有环则可以缩点,之后就成为了DAG,然后用一方法做就好了。

\(Code\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int n, p, r, top, point, cnt, color, ans, belong[100100], stack[100100], lin[100100], low[100010], dfn[100100], data[100100], vis[100100], minn[100010], in[100100];
// 共有几个间谍,                                             被收买的间谍的值, 
struct edge {
	int from, to, nex;
}e[100100];
inline void add(int f, int t)
{
	e[++cnt].from = f;
	e[cnt].to = t;
	e[cnt].nex = lin[f];
	lin[f] = cnt;
}
void tarjan(int u)
{	
	low[u] = dfn[u] = ++point;
	stack[++top] = u;
	vis[u] = 1;
	for(int i = lin[u]; i; i = e[i].nex)
	{
		int v = e[i].to;
		if(!dfn[v]) tarjan(v), low[u] = min(low[u],low[v]);
		else if(vis[v]) low[u] = min(low[u],dfn[v]); 
	}
	if(low[u] == dfn[u])
	{
		color++; 
		int v = 0;
		while(v != u)
		{
			v = stack[top--];
			vis[v] = 0;
			belong[v] = color;
			minn[color] = min(minn[color], data[v]);
		}
	}
}
int main()
{
 	scanf("%d%d", &n, &p);
 	for (int i = 1; i <= n; i++)
		data[i] = 2147483647, minn[i] = 2147483647;
 	for (int i = 1; i <= p; i++)
 	{	
		int a, b;
		scanf("%d%d", &a, &b);
		data[a] = b;
 	}
 	scanf("%d", &r);
 	for (int i = 1; i <= r; i++)
 	{
 		int a, b;
 		scanf("%d%d", &a, &b);
 		add(a, b); 
 	}
 	for (int i = 1; i <= n; i++)
 		if (!dfn[i] && data[i] != 2147483647) tarjan(i);
 	for (int i = 1; i <= n; i++)
 		if (!dfn[i])
 			printf("NO\n%d", i), exit(0);	
 	printf("YES\n");
 	for (int cur = 1; cur <= n; cur++)
		for (int i = lin[cur]; i; i = e[i].nex)		
		{
			int to = e[i].to;
			if (belong[cur] != belong[to])
				in[belong[to]]++;
		}
	for (int i = 1; i <= color; i++)
		if (!in[i])
			ans += minn[i];
	printf("%d", ans);
} 	
posted @ 2019-02-01 20:19  DAGGGGGGGGGGGG  阅读(88)  评论(0编辑  收藏  举报