zoukankan      html  css  js  c++  java
  • tarjan强连通分量 洛谷P1262 间谍网络

    P1262 间谍网络

    题目描述

    由于外国间谍的大量渗入,国家安全正处于高度的危机之中。如果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
    输出样例#1:
    【样例1】
    YES
    110
    【样例2】
    NO
    3


    tarjan模板题,缩点之后算入度为0的
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<vector>
     6 #include<queue>
     7 using namespace std;
     8 int n,p,r,ans,dftm,cnt,top,sum;
     9 struct dt{
    10     int num,cost;
    11 }man[3010];
    12 vector<int>edge[3010];
    13 queue<int>q;
    14 bool check[3010];
    15 int dfn[3010],low[3010],stack[3010],belong[3010],getin[3010],mincost[3010];
    16 int bfs(){
    17     for(int i=1;i<=p;i++){
    18         q.push(man[i].num);
    19         check[man[i].num]=1;
    20     }
    21     int u;
    22     while(!q.empty()){
    23         u=q.front();
    24         q.pop();
    25         for(int i=0;i<edge[u].size();i++)
    26             if(!check[edge[u][i]]){
    27                 check[edge[u][i]]=1;
    28                 q.push(edge[u][i]);
    29             }
    30     }
    31     for(int i=1;i<=n;i++)
    32         if(!check[i]) return i;
    33     return 0;
    34 }
    35 void tarjan(int u){
    36     dfn[u]=++dftm;
    37     low[u]=dftm;
    38     stack[++top]=u;
    39     check[u]=1;
    40     for(int i=0;i<edge[u].size();i++){
    41         if(!dfn[edge[u][i]]){
    42             tarjan(edge[u][i]);
    43             low[u]=min(low[u],low[edge[u][i]]);
    44         }
    45         else if(check[edge[u][i]]) low[u]=min(low[u],dfn[edge[u][i]]);
    46     }
    47     int tmp=0;
    48     if(dfn[u]==low[u]){
    49         cnt++;
    50         do{
    51             tmp=stack[top--];
    52             check[tmp]=0;
    53             belong[tmp]=cnt;
    54         }while(u!=tmp);
    55     }
    56 }
    57 void solve(){
    58     memset(dfn,0,sizeof(dfn));
    59     memset(check,0,sizeof(check));
    60     memset(mincost,0x3f3f3f3f,sizeof(mincost));
    61     for(int i=1;i<=n;i++)
    62         if(!dfn[i]) tarjan(i);
    63     for(int i=1;i<=n;i++)
    64         for(int j=0;j<edge[i].size();j++)
    65             if(belong[i]!=belong[edge[i][j]]) getin[belong[edge[i][j]]]++;
    66     for(int i=1;i<=p;i++) mincost[belong[man[i].num]]=min(mincost[belong[man[i].num]],man[i].cost);
    67     for(int i=1;i<=cnt;i++)
    68         if(!getin[i]) sum+=mincost[i];
    69     printf("YES
    %d
    ",sum);
    70     return;
    71 }
    72 int main(){
    73     scanf("%d%d",&n,&p);
    74     for(int i=1;i<=p;i++) scanf("%d%d",&man[i].num,&man[i].cost);
    75     scanf("%d",&r);
    76     int x,y;
    77     for(int i=1;i<=r;i++){
    78         scanf("%d%d",&x,&y);
    79         edge[x].push_back(y);
    80     }
    81     ans=bfs();
    82     if(ans){
    83         printf("NO
    %d",ans);
    84         return 0;
    85     }
    86     solve();
    87     return 0;
    88 }
     
  • 相关阅读:
    内置函数二
    通信的几个程序
    TCP协议和UDP协议
    异常处理
    logging模块
    网络编程一些概念
    hashlib
    序列化模块
    time,sys,os模块
    random模块
  • 原文地址:https://www.cnblogs.com/zwube/p/7077698.html
Copyright © 2011-2022 走看看