【codevs4093】 EZ的间谍网络 强连通分量+tarjan缩点
2016-11-17 08:18
281 查看
题目描述
由于外国间谍的大量渗入,国家安全正处于高度的危机之中。如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B。有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意交出手中掌握的全部情报。所以,如果我们能够收买一些间谍的话,我们就可能控制间谍网中的每一分子。因为一旦我们逮捕了一个间谍,他手中掌握的情报都将归我们所有,这样就有可能逮捕新的间谍,掌握新的情报。
我们的反间谍机关提供了一份资料,色括所有已知的受贿的间谍,以及他们愿意收受的具体数额。同时我们还知道哪些间谍手中具体掌握了哪些间谍的资料。假设总共有n个间谍(n不超过3000),每个间谍分别用1到3000的整数来标识。
请根据这份资料,判断我们是否有可能控制全部的间谍,如果可以,求出我们所需要支付的最少资金。否则,输出不能被控制的一个间谍。
输入输出格式
输入格式:
第一行只有一个整数n。
第二行是整数p。表示愿意被收买的人数,1≤p≤n。
接下来的p行,每行有两个整数,第一个数是一个愿意被收买的间谍的编号,第二个数表示他将会被收买的数额。这个数额不超过20000。
紧跟着一行只有一个整数r,1≤r≤8000。然后r行,每行两个正整数,表示数对(A, B),A间谍掌握B间谍的证据。
输出格式:
如果可以控制所有间谍,第一行输出YES,并在第二行输出所需要支付的贿金最小值。否则输出NO,并在第二行输出不能控制的间谍中,编号最小的间谍编号。
输入输出样例
输入样例#1:
【样例1】
3
2
1 10
2 100
2
1 3
2 3
【样例2】
4
2
1 100
4 200
2
1 2
3 4
题解:很明显是用tarjan缩点求强连通分量,不过在此基础上维护三个数组,ans,ru,color。
ans:每个强连通分量里收买花费最少的间谍的费用,若没有能收买的就赋为极大值。
ru:判断有没有两个强连通分量是相连的,如:x->y,那么y的入度加一,那么只需要计算入度为0的点就可以。
color:相当于记录每个点存在于哪个强连通分量里。
维护三个数组,最后统计入度为0的所有强连通分量的最低间谍价格就行。
代码:
由于外国间谍的大量渗入,国家安全正处于高度的危机之中。如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B。有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意交出手中掌握的全部情报。所以,如果我们能够收买一些间谍的话,我们就可能控制间谍网中的每一分子。因为一旦我们逮捕了一个间谍,他手中掌握的情报都将归我们所有,这样就有可能逮捕新的间谍,掌握新的情报。
我们的反间谍机关提供了一份资料,色括所有已知的受贿的间谍,以及他们愿意收受的具体数额。同时我们还知道哪些间谍手中具体掌握了哪些间谍的资料。假设总共有n个间谍(n不超过3000),每个间谍分别用1到3000的整数来标识。
请根据这份资料,判断我们是否有可能控制全部的间谍,如果可以,求出我们所需要支付的最少资金。否则,输出不能被控制的一个间谍。
输入输出格式
输入格式:
第一行只有一个整数n。
第二行是整数p。表示愿意被收买的人数,1≤p≤n。
接下来的p行,每行有两个整数,第一个数是一个愿意被收买的间谍的编号,第二个数表示他将会被收买的数额。这个数额不超过20000。
紧跟着一行只有一个整数r,1≤r≤8000。然后r行,每行两个正整数,表示数对(A, B),A间谍掌握B间谍的证据。
输出格式:
如果可以控制所有间谍,第一行输出YES,并在第二行输出所需要支付的贿金最小值。否则输出NO,并在第二行输出不能控制的间谍中,编号最小的间谍编号。
输入输出样例
输入样例#1:
【样例1】
3
2
1 10
2 100
2
1 3
2 3
【样例2】
4
2
1 100
4 200
2
1 2
3 4
题解:很明显是用tarjan缩点求强连通分量,不过在此基础上维护三个数组,ans,ru,color。
ans:每个强连通分量里收买花费最少的间谍的费用,若没有能收买的就赋为极大值。
ru:判断有没有两个强连通分量是相连的,如:x->y,那么y的入度加一,那么只需要计算入度为0的点就可以。
color:相当于记录每个点存在于哪个强连通分量里。
维护三个数组,最后统计入度为0的所有强连通分量的最低间谍价格就行。
代码:
#include<iostream> #include<cstdio> #include<cstring> #define N 10006 using namespace std; struct node { int from,to,next; }e ; int low ,dfn ,insex,stack ,tot; bool instack ; int t,ans ; int e_num,head ; bool flag ; int r,n,p,num ,color ,ru ; int a ,b ,s ; void add(int from,int to) { ++e_num; e[e_num].from=from; e[e_num].to=to; e[e_num].next=head[from]; head[from]=e_num; } void tarjan(int u) { int i; low[u]=dfn[u]=++insex; instack[u]=true; stack[++tot]=u; for (i=head[u];i;i=e[i].next) { int v=e[i].to; if (!dfn[v]) { tarjan(v); low[u]=min(low[v],low[u]); } else if (instack[v]) { low[u]=min(low[u],dfn[v]); } } if (low[u]==dfn[u]) { int tmp=0; ++t; while (tmp!=u) { tmp=stack[tot--]; instack[tmp]=false; ans[t]=min(ans[t],s[tmp]); color[tmp]=t; } } } void slove() { int i; memset(dfn,0,sizeof(dfn)); for (i=1;i<=n;i++) if (!dfn[i]) tarjan(i); } int main() { int x,y,i,sum=0; scanf("%d",&n); scanf("%d",&p); memset(s,127/3,sizeof(s)); for (i=1;i<=p;i++) { scanf("%d%d",&x,&y); s[x]=y; } scanf("%d",&r); for (i=1;i<=r;i++) { scanf("%d%d",&x,&y); add(x,y); a[i]=x;b[i]=y; //x指向y } memset(ans,127/3,sizeof(ans)); int maxx=ans[0]; slove(); int tt=t; for (i=1;i<=r;i++) { if (color[a[i]]!=color[b[i]]) { ru[color[b[i]]]++; } } bool pp; int k; for (i=1;i<=t;i++) if (ans[i]==maxx&&!ru[i]) {pp=1;k=i;break;} if (pp==1) { for (i=1;i<=n;i++) if (color[i]==k) {printf("NO\n%d",i);return 0;} } for (i=1;i<=tt;i++) if (ru[i]==0&&ans[i]!=maxx) sum+=ans[i]; printf("YES\n%d",sum); }
相关文章推荐
- 【codevs4093】EZ的间谍网络 tarjan
- 【基础练习】【强连通tarjan】codevs4093 EZ的间谍网络题解
- 【CodeVS4093】EZ的间谍网络
- codevs 4093 EZ的间谍网络
- tyvj 1153间谍网络 tarjan+缩点
- tarjan缩点以及链式前向星的基本+应用(洛谷1262 间谍网络)
- tarjan强连通分量 洛谷P1262 间谍网络
- CODEVS 4093 EZ的间谍网络
- luogu1262 间谍网络(tarjan缩点)
- 洛谷1262间谍网络(tarjan缩点)
- EZ的间谍网络(codevs 4093)
- 洛谷1262 间谍网络 tarjan缩点
- P1262 间谍网络 (tarjan缩点 水过去)
- P1262 间谍网络 (tarjan缩点 水过去)
- Tarjan缩点【p1262】间谍网络
- 间谍网络(tarjan缩点)
- 【codevs2822】爱在心中 tarjan 缩点+理解
- 连通分量模板:tarjan: 求割点 && 桥 && 缩点 && 强连通分量 && 双连通分量 && LCA(最近公共祖先)
- 洛谷 1262 间谍网络 Tarjan 图论
- 洛谷 1262 间谍网络 Tarjan 图论