zoukankan      html  css  js  c++  java
  • 洛谷P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm

    题目链接:https://www.luogu.org/problem/P2921

    思路:

    这个题目我们可以先把强连通分量求出来,(强连通分量:在该子图中如果v->u,那么u->v一定成立)。

    然后如果一个强连通分量的点数大于等于2,说明该强连通分量成环,而等于1的强连通分量,

    要么自己成环,要么直接或间接连着一个环。

    那么我们先用tarjan求强连通分量,然后处理下缩点后的有向无环图就好解决了。


      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <queue>
      6 #include <stack>
      7 #include <map>
      8 #include <cmath>
      9 #include <iomanip>
     10 using namespace std;
     11 
     12 typedef long long LL;
     13 #define inf (1LL << 25)
     14 #define rep(i,j,k) for(int i = (j); i <= (k); i++)
     15 #define rep__(i,j,k) for(int i = (j); i < (k); i++)
     16 #define per(i,j,k) for(int i = (j); i >= (k); i--)
     17 #define per__(i,j,k) for(int i = (j); i > (k); i--)
     18 
     19 const int N = 100010;
     20 int DFN[N];
     21 int LOW[N];
     22 bool insta[N];
     23 int sccno[N]; //NO.x 编号
     24 int sccdeep[N]; //分量深度
     25 int head[N];
     26 bool visscc[N]; //缩点后的有向无环图访问情况
     27 stack<int> sta;
     28 vector<int> scc[N];
     29 int scccnt,dfn,cnt;
     30 int n;
     31 
     32 struct Edge{
     33     int loc;
     34     int to;
     35     int next;
     36 }e[N];
     37 
     38 void add(int u,int v){
     39     e[cnt].loc = u;
     40     e[cnt].to = v;
     41     e[cnt].next = head[u];
     42     head[u] = cnt++;
     43 }
     44 
     45 void tarjan(int u){
     46 
     47     
     48     DFN[u] = LOW[u] = ++dfn;
     49     sta.push(u);
     50     insta[u] = true;
     51 
     52     for(int o = head[u]; ~o; o = e[o].next){
     53         int v = e[o].to;
     54 
     55         if(!DFN[v]){
     56             tarjan(v);
     57             LOW[u] = min(LOW[u],LOW[v]);
     58         }
     59         else if(insta[v]){
     60             LOW[u] = min(LOW[u],DFN[v]);
     61         }
     62     }
     63 
     64     if(LOW[u] == DFN[u]){
     65         ++scccnt;
     66         scc[scccnt].clear();
     67         while(1){    
     68             int v = sta.top();
     69             sta.pop();
     70             sccno[v] = scccnt; //缩点
     71             insta[v] = false;
     72             scc[scccnt].push_back(v); //缩点
     73             
     74             if(v == u) break;
     75         }
     76 
     77         sccdeep[scccnt] = scc[scccnt].size(); //包含几个点
     78         // cout << scccnt << " num " << sccdeep[scccnt] << endl;
     79     }
     80 }
     81 
     82 void dfs(int ucnt){
     83 
     84     //xcnt  属于哪一块分量
     85 
     86     int u = scc[ucnt][0]; //该点
     87     visscc[ucnt] = true;
     88     for(int o = head[u]; ~o; o = e[o].next){
     89         int v = e[o].to; //去的点
     90         int vcnt = sccno[v]; 
     91         if(v == u) break;//自己成环
     92         if(visscc[vcnt]) sccdeep[ucnt] += sccdeep[vcnt];
     93         else{
     94             dfs(vcnt);
     95             sccdeep[ucnt] += sccdeep[vcnt];
     96         }
     97 
     98         /*这里给一组数据方便理解
     99             5
    100             2
    101             3
              1
    102 5 103 1 104 */ 105 } 106 } 107 108 void print(){ 109 110 rep(i,1,n){ 111 cout << sccdeep[sccno[i]] << endl; 112 } 113 } 114 115 int main(){ 116 117 ios::sync_with_stdio(false); 118 cin.tie(0); 119 120 cin >> n; 121 122 rep(i,1,n) head[i] = -1; // 123 cnt = 0; //边数 124 int v; 125 rep(u,1,n){ 126 cin >> v; 127 add(u,v); 128 } 129 130 // rep(i,1,n){ 131 // for(int o = head[i]; ~o; o = e[o].next) 132 // cout << i << ' ' << e[o].to << endl; 133 // } 134 135 rep(i,1,n) insta[i] = sccno[i] = DFN[i] = LOW[i] = sccdeep[i] = 0; 136 scccnt = dfn = 0; 137 rep(i,1,n) if(!DFN[i]){ 138 tarjan(i); 139 } 140 141 142 rep(i,1,scccnt) if(sccdeep[i] >= 2) visscc[i] = true; //点数超过2个的分量是环,先处理了 143 rep(i,1,scccnt) if(!visscc[i]){ 144 dfs(i); 145 } 146 147 print(); 148 149 getchar(); getchar(); 150 return 0; 151 }
  • 相关阅读:
    回调函数中调用类中的非静态成员变量或非静态成员函数
    [NewCoder]复杂链表的复制
    C++对象模型--总结
    chunk writer 中需要对抛错的交易进行回滚,同时又要在其他表中记录是哪一笔交易记录失败
    为什么因式分解n=pq分别得到pq是求解密钥中d的关键
    DB2 创建数据库
    socket 收发报文小程序
    Zbrush Topogun 备忘
    过度科目理解
    借贷记账思考2015.12.28
  • 原文地址:https://www.cnblogs.com/SSummerZzz/p/11361326.html
Copyright © 2011-2022 走看看