P1153 间谍网络
时间: 1000ms / 空间: 131072KiB / Java类名: Main
描述
由于外国间谍的大量渗入,国家安全正处于高度危机之中。如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B。有些间谍接受贿赂,只要给他们一定数量的美元,他们就愿意交出手中掌握的全部情报。所以,如果我们能够收买一些间谍的话,我们就可能控制间谍网中的每一分子。因为一旦我们逮捕了一个间谍,他手中掌握的情报都将归我们所有,这样就有可能逮捕新的间谍,掌握新的情报。
我们的反间谍机关提供了一份资料,包括所有已知的受贿的间谍,以及他们愿意收受的具体数额。同时我们还知道哪些间谍手中具体掌握了哪些间谍的资料。假设总共有n个间谍(n不超过3000),每个间谍分别用1到3000的整数来标识。
请根据这份资料,判断我们是否可能控制全部的间谍,如果可以,求出我们所需要支付的最少资金。否则,输出不能被控制的一个间谍。
我们的反间谍机关提供了一份资料,包括所有已知的受贿的间谍,以及他们愿意收受的具体数额。同时我们还知道哪些间谍手中具体掌握了哪些间谍的资料。假设总共有n个间谍(n不超过3000),每个间谍分别用1到3000的整数来标识。
请根据这份资料,判断我们是否可能控制全部的间谍,如果可以,求出我们所需要支付的最少资金。否则,输出不能被控制的一个间谍。
输入格式
一行只有一个整数n。
第二行是整数p。表示愿意被收买的人数,1<=p<=n。
接下来的p行,每行有两个整数,第一个数是一个愿意被收买的间谍的编号,第二个数表示他将会被收买的数额。这个数额不超过20000.
紧跟着一行只有一个整数r,1<=r<=8000。然后r行,每行两个正整数,表示数对(A,B),A间谍掌握B间谍的证据。
第二行是整数p。表示愿意被收买的人数,1<=p<=n。
接下来的p行,每行有两个整数,第一个数是一个愿意被收买的间谍的编号,第二个数表示他将会被收买的数额。这个数额不超过20000.
紧跟着一行只有一个整数r,1<=r<=8000。然后r行,每行两个正整数,表示数对(A,B),A间谍掌握B间谍的证据。
输出格式
如果可以控制所有间谍,第一行输出YES,并在第二行输出所需要支付的贿金最小值。否则输出NO,并在第二行输出不能控制的间谍中,编号最小的间谍编号。
测试样例1
输入
2
1
2 512
2
1 2
2 1
输出
YES
512
解题:强连通缩点,看看入度为0 的强连通块中哪个最小选哪个。。。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 4000; 4 const int INF = 0x3f3f3f3f; 5 struct arc { 6 int to,next; 7 arc(int x = 0,int y = -1) { 8 to = x; 9 next = y; 10 } 11 } e[500000]; 12 int head[maxn],dfn[maxn],low[maxn],belong[maxn]; 13 int minV[maxn],value[maxn],in[maxn],tot,idx,scc,n,m; 14 bool instack[maxn]; 15 stack<int>stk; 16 void init() { 17 for(int i = 0; i < maxn; ++i) { 18 dfn[i] = low[i] = head[i] = -1; 19 instack[i] = false; 20 minV[i] = value[i] = INF; 21 in[i] = belong[i] = 0; 22 } 23 tot = scc = idx = 0; 24 while(!stk.empty()) stk.pop(); 25 } 26 void add(int u,int v) { 27 e[tot] = arc(v,head[u]); 28 head[u] = tot++; 29 } 30 void tarjan(int u) { 31 dfn[u] = low[u] = ++idx; 32 instack[u] = true; 33 stk.push(u); 34 for(int i = head[u]; ~i; i = e[i].next) { 35 if(dfn[e[i].to] == -1) { 36 tarjan(e[i].to); 37 low[u] = min(low[u],low[e[i].to]); 38 } else if(instack[e[i].to]) low[u] = min(low[u],dfn[e[i].to]); 39 } 40 if(low[u] == dfn[u]) { 41 scc++; 42 int v; 43 do { 44 instack[v = stk.top()] = false; 45 stk.pop(); 46 belong[v] = scc; 47 } while(v != u); 48 } 49 } 50 int main() { 51 int u,v,w; 52 while(~scanf("%d",&n)) { 53 init(); 54 scanf("%d",&m); 55 for(int i = 1; i <= m; ++i) { 56 scanf("%d %d",&u,&w); 57 value[u] = w; 58 } 59 scanf("%d",&m); 60 while(m--) { 61 scanf("%d %d",&u,&v); 62 add(u,v); 63 } 64 for(int i = 1; i <= n; ++i) 65 if(dfn[i] == -1) tarjan(i); 66 int ans = 0; 67 for(int i = 1; i <= n; ++i) { 68 minV[belong[i]] = min(minV[belong[i]],value[i]); 69 for(int j = head[i]; ~j; j = e[j].next) { 70 if(belong[i] != belong[e[j].to]) in[belong[e[j].to]]++; 71 minV[belong[e[j].to]] = min(minV[belong[e[j].to]],value[e[j].to]); 72 } 73 } 74 for(int i = 1; i <= scc; ++i) 75 if(!in[i]) { 76 if(minV[i] == INF) { 77 ans = INF; 78 break; 79 } 80 ans += minV[i]; 81 } 82 if(ans < INF) printf("%s\n%d\n","YES",ans); 83 else{ 84 for(int i = 1; i <= n; ++i) 85 if(in[belong[i]] == 0 && minV[belong[i]] == INF && value[i] == INF){ 86 ans = i; 87 break; 88 } 89 printf("%s\n%d\n","NO",ans); 90 } 91 } 92 return 0; 93 }