luogu P1262 间谍网络

嘟嘟嘟

建图还是很明显的。

接着分两种情况:

1.图中不存在环:那么只要收买那些入度为0的点。如果这些点有的不能收买。就不能控制所有间谍。

2.图中存在环,那么对于这些在环中的点,我们只要收买数额最少的间谍。

于是我们用tarjan缩点:这样把第二种情况就变成了第一种情况。

所以大体流程是:用tarjan缩点,然后统计新图中入度为0的点愿意收买的数额。缩点的时候可以顺便维护每一个强联通分量的数额的最小值以及编号最小的节点。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cctype>
  8 #include<vector>
  9 #include<stack>
 10 #include<queue>
 11 using namespace std;
 12 #define enter puts("") 
 13 #define space putchar(' ')
 14 #define Mem(a, x) memset(a, x, sizeof(a))
 15 #define rg register
 16 typedef long long ll;
 17 typedef double db;
 18 const int INF = 0x3f3f3f3f;
 19 const db eps = 1e-8;
 20 const int maxn = 2e4 + 5;
 21 inline ll read()
 22 {
 23     ll ans = 0;
 24     char ch = getchar(), last = ' ';
 25     while(!isdigit(ch)) {last = ch; ch = getchar();}
 26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
 27     if(last == '-') ans = -ans;
 28     return ans;
 29 }
 30 inline void write(ll x)
 31 {
 32     if(x < 0) x = -x, putchar('-');
 33     if(x >= 10) write(x / 10);
 34     putchar(x % 10 + '0');
 35 }
 36 
 37 int n, m, r, a[maxn];
 38 vector<int> v[maxn];
 39 
 40 bool in[maxn];
 41 int dfn[maxn], low[maxn], cnt = 0;
 42 stack<int> st;
 43 int ccol = 0, col[maxn], val[maxn], Min[maxn];
 44 void tarjan(int now)
 45 {
 46     dfn[now] = low[now] = ++cnt;
 47     st.push(now); in[now] = 1;
 48     for(int i = 0; i < (int)v[now].size(); ++i)
 49     {
 50         if(!dfn[v[now][i]])
 51         {
 52             tarjan(v[now][i]);
 53             low[now] = min(low[now], low[v[now][i]]);
 54         }
 55         else if(in[v[now][i]]) low[now] = min(low[now], dfn[v[now][i]]);
 56     }
 57     if(dfn[now] == low[now])
 58     {
 59         int x;
 60         ++ccol;
 61         do
 62         {
 63             x = st.top(); st.pop();
 64             in[x] = 0;    
 65             col[x] = ccol;
 66             val[ccol] = min(val[ccol], a[x]);
 67             Min[ccol] = min(Min[ccol], x);
 68             
 69         }while(x != now);
 70     }
 71 }
 72 
 73 int du[maxn];
 74 void newGraph(int now)
 75 {
 76     int u = col[now];
 77     for(int i = 0; i < (int)v[now].size(); ++i)
 78     {
 79         int e = col[v[now][i]];
 80         if(u == e) continue;
 81         du[e]++;
 82     }
 83 }
 84 
 85 int main()
 86 {
 87     n = read(); m = read();
 88     for(int i = 1; i <= n; ++i) a[i] = val[i] = Min[i] = INF;
 89     for(int i = 1; i <= m; ++i)
 90     {
 91         int x = read(), y = read();
 92         a[x] = y;
 93     }
 94     r = read();
 95     for(int i = 1; i <= r; ++i)
 96     {
 97         int x = read(), y = read();
 98         v[x].push_back(y); 
 99     }
100     for(int i = 1; i <= n; ++i) if(!dfn[i]) tarjan(i);
101     for(int i = 1; i <= n; ++i) newGraph(i);
102     int sum = 0, Mn = INF;
103     for(int i = 1; i <= ccol; ++i) if(!du[i]) 
104     {
105         if(val[i] == INF) Mn = min(Mn, Min[i]);        //如果这个点不能收买 
106         else sum += val[i];
107     }
108     if(Mn != INF) printf("NO
%d
", Mn);
109     else printf("YES
%d
", sum);
110     return 0;
111 }
112  
View Code
原文地址:https://www.cnblogs.com/mrclr/p/9663563.html