fzu 1719 Spy Network(强连通分量)

 Problem 1719 Spy Network

Accept: 41    Submit: 169
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 Problem Description

Due to the large number of infiltration of foreign espionage, national security is at a high level of crisis. If Spy A grasps Spy B’s evidence of crimes, Spy A can exposed Spy B. Some spies take bribes, and if we give a number of dollars to them, they are willing to hand over all their evidences they have. Therefore, if we are able to buy some spies, we would control the whole spy network.
That is because once we arrest a spy, we will get all evidences he has. Then we can arrest new spies to acquire new information.
Now we know those who are willing to take dollars, and the number of dollars they need. We know what evidences have been got for each spy as well. Suppose that there are n (n <= 3000) spies in total, who are labeled as a number between 1 and n.If we can control all spies, output minimal dollars required, otherwise output each spies we cannot control.

 Input

The input consists of several test cases.For each case,the first line of input is an integer n. The second line is an integer p (1<=p<=n), which is the number of spies who accept dollars.Then following p lines, each of them contains two integers indicating the label of spies and the number he needs. An integer r (1 <= r <= 8000) followed, then r lines. Each contains two integers A and B, which means that Spy A has the evidence of Spy B.

 Output

For each case, If we can control all spies, output “YES” in the first line and the minimal number of dollar we need in the second line. If we cannot, output “NO” in the first line and the label of spy that we cannot control and have the minimal number of label.

 Sample Input

321 102 10021 32 3421 1004 20021 23 4

 Sample Output

YES110NO3

 Source

FZU 2009 Summer Training Qualification -- Hero Revival 1
分析: 缩点后的价值取环内最小的价值,然后把入度为0的间谍全部买下来是去省钱的方式,如果不能买就输出NO
代码:
#include<cstdio>
#define min(a,b) a<b?a:b
using namespace std;
const int mm=8008;
const int mn=3003;
const int oo=1000000000;
int s[mm],t[mm],p[mm];
int h[mn],id[mn],q[mn],dfn[mn],low[mn],w[mn],x[mn];
int i,j,k,n,m,tsp,qe,cnt,ans;
void dfs(int u)
{
    int i,v;
    dfn[u]=low[u]=++tsp;
    q[qe++]=u;
    for(i=h[u];i>=0;i=p[i])
        if(!dfn[v=t[i]])
            dfs(v),low[u]=min(low[u],low[v]);
        else if(id[v]<0)low[u]=min(low[u],dfn[v]);
    if(low[u]==dfn[u])
    {
        id[u]=++cnt;
        while((v=q[--qe])!=u)id[v]=cnt;
    }
}
void tarjan()
{
    int i;
    for(qe=tsp=cnt=i=0;i<=n;++i)dfn[i]=0,id[i]=-1;
    for(i=1;i<=n;++i)
        if(!dfn[i])dfs(i);
}
int main()
{
    while(scanf("%d%d",&n,&m)!=-1)
    {
        for(i=1;i<=n;++i)w[i]=oo,h[i]=-1;
        while(m--)scanf("%d%d",&i,&j),w[i]=j;
        scanf("%d",&m);
        for(k=0;k<m;++k)
        {
            scanf("%d%d",&i,&j);
            s[k]=i,t[k]=j,p[k]=h[i],h[i]=k;
        }
        tarjan();
        for(i=1;i<=cnt;++i)x[i]=oo,q[i]=0;
        for(i=1;i<=n;++i)x[id[i]]=min(x[id[i]],w[i]);
        for(k=0;k<m;++k)
            if(id[s[k]]!=(i=id[t[k]]))++q[i];
        for(i=1;i<=cnt;++i)
            if(!q[i]&&x[i]>=oo)break;
        if(i<=cnt)
        {
            printf("NO\n");
            for(j=1;j<=n;++j)
                if(id[j]==i)break;
            printf("%d\n",j);
            continue;
        }
        for(ans=0,i=1;i<=cnt;++i)
            if(!q[i]&&x[i]<oo)ans+=x[i];
        printf("YES\n%d\n",ans);
    }
    return 0;
}


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值