间谍网络(AGE)

Simulation 10 Problem 1

题目描述

  由于外国间谍的大量渗入,国家安全正处于高度的危机之中。如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B。有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意交出手中掌握的全部情报。所以,如果我们能够收买一些间谍的话,我们就可能控制间谍网中的每一分子。因为一旦我们逮捕了一个间谍,他手中掌握的情报都将归我们所有,这样就有可能逮捕新的间谍,掌握新的情报。

    我们的反间谍机关提供了一份资料,色括所有已知的受贿的间谍,以及他们愿意收受的具体数额。同时我们还知道哪些间谍手中具体掌握了哪些间谍的资料。假设总共有n个间谍(n不超过3000),每个间谍分别用1到3000的整数来标识。

    请根据这份资料,判断我们是否有可能控制全部的间谍,如果可以,求出我们所需要支付的最少资金。否则,输出不能被控制的一个间谍。

分析

  题目比较弱,数据范围很弱,真正的数据尤其弱。

  先拓扑排序,入度为0且可以收买就收买了,这一定是最优的。

  然后就找环,比较坑的是你找不到环就NO了,但这个环里的个别人可能能被控制,所以还要判断谁能被控制,在找NO后面的数。

  ps:这题大家都用的强连通分量缩点,但我在听他们讲题之前就没听说过。。。

    不过即使不知道还是A了这道数据蒟蒻的题\(^o^)/~

  1 /**************************************************
  2           Origin: Simulation 10 Problem 1
  3           Author: Xue Zhonghao
  4           Data: 2014-4-14 18:30:17 
  5           State: Accepted
  6 **************************************************/
  7 #include<cstdio>
  8 #include<stack>
  9 #include<fstream>
 10 using namespace std;
 11 ifstream fin("age.in");
 12 ofstream fout("age.out");
 13 
 14 #define MAXN 3010
 15 
 16 int od[MAXN][MAXN];
 17 int id[MAXN][MAXN];
 18 int can[MAXN];
 19 int value[MAXN];
 20 int done[MAXN];
 21 int dtd = 0;
 22 
 23 void remove(int k) {
 24     done[k] = 1; dtd++;
 25     for(int i = 1; i <= od[k][0]; ++i)
 26       if(!done[od[k][i]]) remove(od[k][i]);
 27 }
 28 
 29 int getc(int k) {
 30     int v[MAXN], d[MAXN];
 31     memset(v, 0, sizeof(v));
 32     memset(d, 0, sizeof(d));
 33     d[1] = k;
 34     v[k] = 1;
 35     int i = 0, j = 1;
 36     do {
 37       i++;//if(d[i] == 1) fout<<"!!!!!!"<<endl;
 38       for(int z = 1; z <= id[d[i]][0]; ++z)
 39         if(!done[id[d[i]][z]]) {
 40           if(v[id[d[i]][z]]) return id[d[i]][z];
 41           v[id[d[i]][z]] = 1;
 42           d[++j] = id[d[i]][z];
 43         }
 44     }while(i < j);
 45     return -1;
 46 }
 47 
 48 int cir(int k) {
 49     int r = getc(k);
 50     if(r == -1) {
 51       if(can[k]) { remove(k); return value[k]; }
 52       else return -1;
 53     }
 54     int v[MAXN], d[MAXN];
 55     memset(v, 0, sizeof(v));
 56     memset(d, 0, sizeof(d));
 57     d[1] = r;
 58     v[r] = 1;
 59     int i = 0, j = 1, min = 50000;
 60     do {
 61       i++;//if(d[i] == 1) fout<<"!!!!!!"<<endl;
 62       if(can[d[i]] && min > value[d[i]]) min = value[d[i]];
 63       for(int z = 1; z <= id[d[i]][0]; ++z)
 64         if(!done[id[d[i]][z]] && !v[id[d[i]][z]]) {
 65           v[id[d[i]][z]] = 1;
 66           d[++j] = id[d[i]][z];
 67         }
 68     }while(i < j);
 69     if(min == 50000) return -1;
 70     remove(r);
 71     return min;
 72 }
 73 
 74 int main(void)
 75 {
 76     int N, total = 0;
 77     int x, y, p;
 78     fin>>N;
 79     fin>>p;
 80     for(int i = 0; i < p; ++i) {
 81       fin>>x>>y;
 82       can[x] = 1;
 83       value[x] = y;
 84     }
 85     int r;
 86     fin>>r;
 87     for(int i = 0; i < r; ++i) {
 88       fin>>x>>y;
 89       od[x][++od[x][0]] = y;
 90       id[y][++id[y][0]] = x;
 91     }
 92     for(int i = 1; i <= N; ++i)
 93       if(can[i] && id[i][0] == 0) {
 94         total += value[i];
 95         remove(i);
 96       }
 97     if(dtd == N) {
 98       fout<<"YES"<<endl;
 99       fout<<total<<endl;
100       return 0;
101     }
102     for(int i = 1; i <= N; ++i)
103       if(!done[i]) {
104         p = cir(i);
105         if(p == -1) {
106           fout<<"NO"<<endl;
107           fout<<i<<endl;
108           return 0;
109         }
110         total += p;
111         if(dtd == N) break;
112       }
113     fout<<"YES"<<endl;
114     fout<<total<<endl;
115     return 0;
116 }

 

转载于:https://www.cnblogs.com/xuezhonghao/p/3664951.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值