数据范围好小啊(小声)
首先对于环 , 我们可以直接缩成点 , 如果环上的有好多可以收买的间谍的话就找其中要价最低的作为这个缩点后的点的要价
然后怎么处理呐?
我做完以后看到题解区有神仙一个循环就能处理出答案
但是我太菜了自己做的时候并没有想到qaq
所以就用了 DFS
再建一个缩点后的图 , 然后从每一个可以被收买的点上 DFS , 最后看看有没有点没有被搜到就可以了
如果说从一个可以被收买的点 a , 搜的时候找到了另一个已经搜过而且也是可以被收买的点 b
那么就不用买 b 了, 就买个 a 就可以了
当然这个 DFS 复杂度显然 O(n)
代码:
1 #include<cmath> 2 #include<stack> 3 #include<vector> 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 #include<iostream> 8 #include<algorithm> 9 #define APART puts("----------------------") 10 #define debug 1 11 #define FILETEST 1 12 #define inf 100010 13 #define ll long long 14 #define ha 998244353 15 #define INF 0x7fffffff 16 #define INF_T 9223372036854775807 17 #define DEBUG printf("%s %d\n",__FUNCTION__,__LINE__) 18 19 namespace chino{ 20 21 inline void setting(){ 22 #if FILETEST 23 freopen("_test.in", "r", stdin); 24 freopen("_test.me.out", "w", stdout); 25 #endif 26 return; 27 } 28 29 inline int read(){ 30 char c = getchar(), up = c; int num = 0; 31 for(; c < ‘0‘ || c > ‘9‘; up = c, c = getchar()); 32 for(; c >= ‘0‘ && c <= ‘9‘; num = (num << 3) + (num << 1) + (c ^ ‘0‘), c = getchar()); 33 return up == ‘-‘ ? -num : num; 34 } 35 36 int n, m, o; 37 int ans; 38 int cntE, cntR, cntJ, cntT; 39 int val[inf], root[inf]; 40 int belong[inf], in[inf]; 41 int low[inf], dfn[inf], vis[inf]; 42 int head[inf], rehead[inf]; 43 struct Edge{ 44 int to; 45 int next; 46 }e[inf << 1], r[inf << 1]; 47 std::stack <int> S; 48 std::vector <int> V; 49 50 inline void AddEdge 51 (int from, int to, int &cntE, int *head, Edge *e){ 52 ++cntE; 53 e[cntE].to = to; 54 e[cntE].next = head[from]; 55 head[from] = cntE; 56 return; 57 } 58 59 void tarjan(int now){ 60 dfn[now] = low[now] = ++cntJ; 61 S.push(now), vis[now] = 1; 62 for(int i = head[now]; i; i = e[i].next){ 63 int to = e[i].to; 64 if(dfn[to] == 0){ 65 tarjan(to); 66 low[now] = std::min (low[to], low[now]); 67 } else if(vis[to]) 68 low[now] = std::min (low[now], dfn[to]); 69 } 70 if(dfn[now] == low[now]){ 71 int top = S.top(); 72 while(true){ 73 top = S.top(), S.pop(); 74 belong[top] = now; 75 vis[top] = 0; 76 for(int i = head[top]; i; i = e[i].next) 77 AddEdge(now, e[i].to, cntR, rehead, r), ++in[e[i].to]; 78 if(top == now) 79 break; 80 val[now] = std::min (val[now], val[top]); 81 } 82 } 83 return; 84 } 85 86 int DFS(int now, int g, int rooty){ 87 if(vis[now] || (rooty == now && g)) 88 return 0; 89 if(root[now]) 90 ans -= val[now]; 91 root[now] = !g; 92 vis[now] = g; 93 for(int i = head[now]; i; i = e[i].next){ 94 int to = e[i].to; 95 to = belong[to]; 96 DFS(to, 1, rooty); 97 } 98 return 1; 99 } 100 101 inline void fail(int point){ 102 puts("NO"); 103 printf("%d\n", point); 104 exit(0); 105 } 106 107 inline int main(){ 108 n = read(); 109 m = read(); 110 std::fill(val + 1, val + 1 + n, INF); 111 for(int i = 1; i <= m; i++){ 112 int u = read(); 113 val[u] = read(); 114 V.push_back(u); 115 } 116 o = read(); 117 for(int i = 1; i <= o; i++){ 118 int u = read(); 119 int v = read(); 120 AddEdge(u, v, cntE, head, e); 121 } 122 for(int i = 1; i <= n; i++){ 123 if(dfn[i] == 0) 124 tarjan(i); 125 } 126 for(int i = 1; i <= n; i++){ 127 if(in[i] == 0 && val[i] == INF) 128 fail(i); 129 } 130 memset(vis, 0, sizeof vis); 131 for(unsigned int i = 0; i < V.size(); i++) 132 ans += val[belong[V[i]]] * DFS(belong[V[i]], 0, belong[V[i]]); 133 for(int i = 1; i <= n; i++){ 134 if(vis[i] == 0 && val[i] == INF && belong[i] == i) 135 fail(i); 136 } 137 puts("YES"); 138 printf("%d\n", ans); 139 return 0; 140 } 141 142 }//namespace chino 143 144 int main(){return chino::main();}
原文地址:https://www.cnblogs.com/chiarochinoful/p/problem-luogu-P1262.html
时间: 2024-10-12 21:19:36