zoukankan      html  css  js  c++  java
  • 洛谷 P1262 【间谍网络】


    思路 :

        这题可以用缩点的思想来做。先用Tarjan算法以一个没有被搜过&&能被收贿赂的点为起点,把每个强连通分量给缩成一个点(一个强连通分量 )(这个强连通分量里的任意一个可以收贿赂的间谍 收贿赂之后,就可以 掌握这个强连通分量中其他间谍的证据),然后我们在搜Tarjan 的时候记得把每个强连通分量中的最小收贿赂值算出来,这个对以后计算答案很有帮助。

        最后就剩下两点了:

    1. 可以掌握所有间谍的证据 : 这个情况是因为搜完Tarjan之后,所有点都在强连通分量里(至于在哪个无所谓,反正都在强连通分量里)。那 么我们只需要把入度为0的强连通分量中的最小收贿赂 值加起来就好了(如果入度不为0,那么这个强连通分量就可以被其他强连通分 量中的间谍掌握证据,这样这个强连通分量就都可以不用收贿赂就被掌握证据了)
    2. 不能掌握所有间谍的证据 : 这个情况是因为当我们搜完Tanjan之后,如果有一个点(间谍)没有被搜到过,他就无法被掌握证据(他不在任何 一个强连通分量中,他既无法被收贿赂,也无法被其 他能收贿赂的间谍掌握证据)。

    注意 :

           你可能会怀疑一个强连通分量中没有任何一个间谍可以收贿赂,当然,这种情况是有的。但如果一个强连通分量被搜到了&&他里面没有可以收 贿赂的间谍,既然他被搜到了,那么一定有一个可以 收贿赂的间谍出   发,最后搜到了当前强连通分量(这个强连通分量的入度肯定不为0, 所以这个担心是多余的)


    解释一下样例:


    code :

      1 #include <bits/stdc++.h>
      2 #define INF 0x3f3f3f3f
      3 using namespace std;
      4 stack < int > pru;
      5 int n, m, M, q[100001], dfn[100001], low[100001], vis[100001], col[100001], head[100001], minn[100001], in[100001], color, num, z, ans;
      6 struct node
      7 {
      8     int next, to;
      9 }stu[100001];
     10 inline void add(int x, int y)//链表存图 
     11 {
     12     stu[++num].next = head[x];
     13     stu[num].to = y;
     14     head[x] = num;
     15     return;
     16 }
     17 inline void tarjan(int u)//Tarjan模板 
     18 {
     19     dfn[u] = low[u] = ++z;
     20     vis[u] = 1;
     21     pru.push(u);
     22     for(register int i = head[u]; i; i = stu[i].next)
     23     {
     24         int k = stu[i].to;
     25         if(!vis[k])
     26         {
     27             tarjan(k);
     28             low[u] = min(low[u], low[k]);
     29         }
     30         else if(!col[k])
     31         {
     32             low[u] = min(low[u], dfn[k]);
     33         }
     34     }
     35     if(dfn[u] == low[u])
     36     {
     37         col[u] = ++color;
     38         minn[color] = min(minn[color], q[u]);//在一个强连通分量中,寻找其中可以贿赂的最小值 
     39         while(pru.top() != u)
     40         {
     41             col[pru.top()] = color;
     42             minn[color] = min(minn[color], q[pru.top()]);//同理 
     43             pru.pop();
     44         }
     45         pru.pop();
     46     }
     47     return;
     48 }
     49 signed main()
     50 {
     51     memset(minn, INF, sizeof(minn));//初始化为最大 
     52     memset(q, INF, sizeof(q));//同理 
     53     scanf("%d %d", &n, &M);
     54     for(register int i = 1, x, y; i <= M; ++i)
     55     {
     56         scanf("%d %d", &x, &y);
     57         q[x] = y;
     58     }
     59     scanf("%d", &m);
     60     for(register int i = 1, x, y; i <= m; ++i)
     61     {
     62         scanf("%d %d", &x, &y);
     63         add(x, y);
     64     }
     65     for(register int i = 1; i <= n; ++i)
     66     {
     67         if(!vis[i] && q[i] != INF)//要判断这人是否可以贿赂 
     68         {
     69             tarjan(i);
     70         }
     71     }
     72     for(register int i = 1; i <= n; ++i)
     73     {
     74         if(!vis[i])//如果有人没被搜到过(及无法掌握这人的证据) 
     75         {
     76             printf("NO
    %d", i);//由于是从小到大(1 ~ n),所以第一个搜到没被搜过的就是最小值 
     77             return 0;
     78         }
     79     }
     80     for(register int u = 1; u <= n; ++u)
     81     {
     82         for(register int i = head[u]; i; i = stu[i].next)//寻找其中入度为0的点 
     83         {
     84             int k = stu[i].to;
     85             if(col[k] != col[u])//颜色不同(及不在一个强连通分量中) 
     86             {
     87                 ++in[col[k]];//k所在的强连通分量的入度++ 
     88             }
     89         }
     90     }
     91     for(register int i = 1; i <= color; ++i)//枚举每个强连通分量 
     92     {
     93         if(!in[i])//没有入度(不能被其他强连通分量中的间谍掌握证据) 
     94         {
     95             ans += minn[i];//这个点中可收贿赂最小的间谍就必须贿赂他 
     96         }
     97     }
     98     printf("YES
    %d", ans);
     99     return 0;
    100 }
  • 相关阅读:
    在线网络考试系统源码
    zabbix通过api 批量自动添加主机
    python 连接数据库 区分线上和测试环境
    python 获取本机ip win or linux
    redis常用参数以及redis内存淘汰机制
    nginx常用配置
    Linux基础命令(之一)详解
    linux系统重要子目录介绍
    Linux系统根目录结构介绍
    Linux 基础优化配置
  • 原文地址:https://www.cnblogs.com/qqq1112/p/11206918.html
Copyright © 2011-2022 走看看