由于外国间谍的大量渗入,学校安全正处于高度的危机之中。YJY决定挺身而作出反抗。如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B。有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意交出手中掌握的全部情报。所以,如果我们能够收买一些间谍的话,我们就可能控制间谍网中的每一分子。因为一旦我们逮捕了一个间谍,他手中掌握的情报都将归我们所有,这样就有可能逮捕新的间谍,掌握新的情报。
我们的神通广大的YJY获得了一份资料,色括所有已知的受贿的间谍,以及他们愿意收受的具体数额。同时我们还知道哪些间谍手中具体掌握了哪些间谍的资料。假设总共有n个间谍(n不超过3000),每个间谍分别用1到3000的整数来标识。
请根据这份资料,判断我们是否有可能控制全部的间谍,如果可以,求出我们所需要支付的最少资金。否则,输出不能被控制的一个间谍。
第一行只有一个整数n。
第二行是整数p。表示愿意被收买的人数,1≤p≤n。
接下来的p行,每行有两个整数,第一个数是一个愿意被收买的间谍的编号,第二个数表示他将会被收买的数额。这个数额不超过20000。
紧跟着一行只有一个整数r,1≤r≤8000。然后r行,每行两个正整数,表示数对(A, B),A间谍掌握B间谍的证据。
如果可以控制所有间谍,第一行输出YES,并在第二行输出所需要支付的贿金最小值。否则输出NO,并在第二行输出不能控制的间谍中,编号最小的间谍编号。
【样例1】
3
2
1 10
2 100
2
1 3
2 3
【样例2】
4
2
1 100
4 200
2
1 2
3 4
【样例1】
YES
110
【样例2】
NO<a name="_GoBack"></a>
3
各个测试点1s
友情提示:请先膜拜下万能的YJY再做呦^_^
对于每个环,环内任意一个元素可以揭发其他所有人 因此只需要把环缩成一点 这点的权值为环上点权值的最小值
如果遇到一条链,由于我们的目的是把所有的间谍都控制,因此必须控制链的起点元素。
在环缩点之后,凡是入度为0的点,要么是独立的点,要么是链的起始点;同时,所有需要被控制的点,即链的起始点和独立点,必然入度为0。因此只需统计入度为零的点权值和。
如果缩点后存在不能被控制的入度为0的点 则需要找出不能控制的点中最小的一个。因此我们在缩点时同时记录这个环中编号最小点,并将不能控制的点权值赋值为极大值。最后我们扫一遍求得编号最小的点即可。
这道题目即使是10s的时间鄙人还是狂T不止。最后试出数据,发现还是错在了低级错误上。遍历边的时候竟然写的是i=next[x]而不是i=next[i],因此i的值始终卡在一个值上,当然会死循环。
代码
//codevs4093 EZ的间谍网络 tarjan
//copyright by ametake
//task:首先缩点 并把点值赋值为最小代价 然后重构图统计入度 对入度为0的点求和
#include
#include
#include
#include
using namespace std;
const int maxn=3000+10;
const int maxm=8000+10;
int n,p,r;
int hd[maxn],tt[maxm*2],nxt[maxm*2],et;
int money[maxn],fin[maxn];
int dfn[maxn],low[maxn],dep=0;
int inwhich[maxn],sta[maxn],stp=0;
bool ins[maxn],ok,ru[maxn][maxn];
int tot,ans,rudu[maxn],mip[maxn];
int read()
{
int a=0;
int f=1;
char ch=getchar();
while (ch>'9'||ch<'0')
{
if (ch=='-') f=-1;
ch=getchar();
}
while (ch<='9'&&ch>='0')
{
a=a*10+ch-'0';
ch=getchar();
}
a*=f;
return a;
}
void add(int x,int y)
{
et++;
tt[et]=y;
nxt[et]=hd[x];
hd[x]=et;
}
void tarjan(int x)
{
dfn[x]=low[x]=++dep;
ins[x]=true;
sta[++stp]=x;
for (int i=hd[x];i!=0;i=nxt[i])
{
if (!dfn[tt[i]])
{
tarjan(tt[i]);
low[x]=min(low[x],low[tt[i]]);
}
else if (ins[tt[i]])
{
low[x]=min(low[x],dfn[tt[i]]);
}
}
if (dfn[x]==low[x])
{
int j;
tot++;
int minn=0x3f3f3f,mij=0x3f3f3f;
do
{
j=sta[stp--];
ins[j]=false;
inwhich[j]=tot;
mij=min(mij,j);
if (money[j]
——槛菊愁烟兰泣露,罗幕轻寒,燕子双飞去