[luogu]P1262 间谍网络 题解

时间:2019-09-21
本文章向大家介绍[luogu]P1262 间谍网络 题解,主要包括[luogu]P1262 间谍网络 题解使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

原题目:[luogu]P1262 间谍网络

数据范围好小啊(小声)

首先对于环 , 我们可以直接缩成点 , 如果环上的有好多可以收买的间谍的话就找其中要价最低的作为这个缩点后的点的要价

然后怎么处理呐?

我做完以后看到题解区有神仙一个循环就能处理出答案

但是我太菜了自己做的时候并没有想到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