洛谷 P1262 间谍网络

来源:互联网 发布:定位软件开发 编辑:程序博客网 时间:2024/05/01 09:20

题目描述
由于外国间谍的大量渗入,国家安全正处于高度的危机之中。如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B。有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意交出手中掌握的全部情报。所以,如果我们能够收买一些间谍的话,我们就可能控制间谍网中的每一分子。因为一旦我们逮捕了一个间谍,他手中掌握的情报都将归我们所有,这样就有可能逮捕新的间谍,掌握新的情报。
我们的反间谍机关提供了一份资料,色括所有已知的受贿的间谍,以及他们愿意收受的具体数额。同时我们还知道哪些间谍手中具体掌握了哪些间谍的资料。假设总共有n个间谍(n不超过3000),每个间谍分别用1到3000的整数来标识。
请根据这份资料,判断我们是否有可能控制全部的间谍,如果可以,求出我们所需要支付的最少资金。否则,输出不能被控制的一个间谍。


【题目分析】
Tarjan。


【代码】

#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;int n,p,x,y,m;int a[3001];int h[3001],to[8001],ne[8001],fr[8001],en=0;int bel[3001],cnt[3001],idx=0,low[3001],dfn[3001],minn[3001],vcnt=0,ins[3001],sta[3001],top=0;int minnum[3001];void add(int a,int b){    fr[en]=a;    to[en]=b;    ne[en]=h[a];    h[a]=en++;}void tarjan(int k){    low[k]=dfn[k]=++idx;    ins[k]=1;    sta[++top]=k;    for (int i=h[k];i>=0;i=ne[i])    {        if (!dfn[to[i]])        {            tarjan(to[i]);            low[k]=min(low[k],low[to[i]]);        }        else if (ins[to[i]]) low[k]=min(low[k],dfn[to[i]]);    }    if (low[k]==dfn[k])    {        int x=-1;        ++vcnt;        while (x!=k)        {            x=sta[top--];            bel[x]=vcnt;            cnt[vcnt]++;            if (a[x]==0) minnum[vcnt]=min(x,minnum[vcnt]);            ins[x]=0;            if (a[x]!=0) minn[vcnt]=min(a[x],minn[vcnt]);        }    }}int h2[3001],to2[8001],ne2[8001],fr2[8001],en2=0;int du[3001];void add2(int a,int b){//    printf("add2 %d %d\n",a,b);    to2[en2]=b;    ne2[en2]=h2[a];    fr2[en2]=a;    h2[en2]=en2++;    du[b]++;}queue <int> q;void prt(){    int vis[3001];     memset(vis,0,sizeof vis);//    printf("its no\n");    int ans=0x3f3f3f3f;    while (!q.empty())    {        int x=q.front(); q.pop(); ans=min(ans,minnum[x]);//        printf("%d \n",minnum[x]);        vis[x]=1;        for (int i=h2[x];i>=0;i=ne2[i]) if (!vis[to2[i]]) q.push(to2[i]);    }    printf("NO\n%d\n",ans);}int main(){    while (!q.empty()) q.pop();    memset(minnum,0x3f,sizeof minnum);    memset(h2,-1,sizeof h2);    memset(minn,0x3f,sizeof minn);    memset(h,-1,sizeof h);    scanf("%d%d",&n,&p);    for (int i=1;i<=p;++i)    {        scanf("%d%d",&x,&y);        a[x]=y;    }    scanf("%d",&m);    for (int i=1;i<=m;++i)    {        int a,b;        scanf("%d%d",&a,&b);        add(a,b);    }    for (int i=1;i<=n;++i) if (!dfn[i]) tarjan(i);//    for (int i=1;i<=n;++i) printf("%d ",bel[i]); printf("\n");//    for (int i=1;i<=n;++i) printf("%d ",minnum[i]); printf("\n");    for (int i=0;i<en;++i)        if (bel[fr[i]]!=bel[to[i]])            add2(bel[fr[i]],bel[to[i]]);    int ans=0,flag=1;    for (int i=1;i<=vcnt;++i)        if (!du[i]){            if (minn[i]==0x3f3f3f3f)            {                q.push(i);                flag=0;//                prtno();//                return 0;            }            else ans+=minn[i];        }    if (flag) printf("YES\n%d\n",ans);    else prt();}
0 0
原创粉丝点击