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 }