• 【tarjan+拓扑】BZOJ3887-[Usaco2015 Jan]Grass Cownoisseur


    【题目大意】

    给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在路径中无论出现多少正整数次对答案的贡献均为1)

    【思路】

    首先缩点,对于每一个联通块求出正图和反图中节点1所在的联通块到它的最长节点数。这个用拓扑排序处理一下。

    枚举每一条边取反,对于边(u,v),其取反后的距离就等于dis[u所在的联通快]+dis[v所在的联通块]-dis[1所在的联通块](因为会被重复计算不要忘记减去)

    我一开始非常脑抽地在想会不会发生这样的情况:本来到u所在的联通块就会经过v,这样不就重复计算点了。要注意缩点之后的图为DAG,如果存在v->u的路径,同时存在u->v的路径,那么必定存在环,矛盾。

    【错误点】

    写x节点所在的联通块的时候,一直写成x节点。千万不要忘记了col[]。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<vector>
      6 #include<stack>
      7 #include<queue>
      8 using namespace std;
      9 const int MAXN=100000+50;
     10 vector<int> E[MAXN];
     11 vector<int> tE[MAXN],rtE[MAXN];
     12 stack<int> S;
     13 int x[MAXN],y[MAXN];
     14 int instack[MAXN],low[MAXN],dfn[MAXN],col[MAXN],size[MAXN],cnt,colcnt;
     15 int dis[MAXN],rdis[MAXN],degree1[MAXN],degree2[MAXN];
     16 int vis[MAXN];
     17 int n,m;
     18 
     19 void Topology1()
     20 {
     21     memset(dis,0xef,sizeof(dis));//初始化为-INF 
     22     queue<int> que;
     23     dis[col[1]]=size[col[1]];
     24     for (int i=1;i<=colcnt;i++)
     25         if (!degree1[i]) que.push(i);
     26     while (!que.empty())
     27     {
     28         int now=que.front();que.pop();
     29         for (int i=0;i<tE[now].size();i++)
     30         {
     31             int to=tE[now][i];
     32             dis[to]=max(dis[to],dis[now]+size[to]);
     33             if (!--degree1[to]) que.push(to);
     34         }
     35     }
     36 }
     37 
     38 void Topology2()
     39 {
     40     memset(rdis,0xef,sizeof(rdis));
     41     queue<int> que;
     42     rdis[col[1]]=size[col[1]];
     43     for (int i=1;i<=colcnt;i++)
     44         if (!degree2[i]) que.push(i);
     45     while (!que.empty())
     46     {
     47         int now=que.front();que.pop();
     48         for (int i=0;i<rtE[now].size();i++)
     49         {
     50             int to=rtE[now][i];
     51             rdis[to]=max(rdis[to],rdis[now]+size[to]);
     52             if (!--degree2[to]) que.push(to);
     53         }
     54     }
     55 }
     56 
     57 
     58 void tarjan(int u)
     59 {
     60     dfn[u]=low[u]=++cnt;
     61     instack[u]=1;
     62     S.push(u);
     63     for (int i=0;i<E[u].size();i++)
     64     {
     65         int v=E[u][i];
     66         if (!instack[v])
     67         {
     68             tarjan(v);
     69             low[u]=min(low[u],low[v]);
     70                 
     71         }
     72         else if (instack[v]==1) low[u]=min(low[u],dfn[v]);
     73     }
     74     
     75     if (dfn[u]==low[u])
     76     {
     77         colcnt++;
     78         int x;
     79         do
     80         {
     81             x=S.top();
     82             col[x]=colcnt;
     83             instack[x]=2;
     84             size[colcnt]++;
     85             S.pop();
     86         }while (x!=u);
     87     }
     88 }
     89 
     90 void init()
     91 {
     92     scanf("%d%d",&n,&m);
     93     for (int i=0;i<m;i++) 
     94     {
     95         scanf("%d%d",&x[i],&y[i]);
     96         E[x[i]].push_back(y[i]);
     97     }
     98     memset(instack,0,sizeof(instack));
     99     cnt=colcnt=0;
    100     for (int i=1;i<=n;i++)
    101         if (!instack[i]) tarjan(i);
    102     for (int i=0;i<m;i++)
    103     {
    104         if (col[x[i]]!=col[y[i]])
    105         {
    106             tE[col[x[i]]].push_back(col[y[i]]);
    107             degree1[col[y[i]]]++;
    108             rtE[col[y[i]]].push_back(col[x[i]]);
    109             degree2[col[x[i]]]++;
    110         }
    111     }
    112 }
    113 
    114 void solve()
    115 {
    116     memset(dis,0,sizeof(dis));
    117     memset(rdis,0,sizeof(rdis));
    118     Topology1();
    119     Topology2();
    120     int ans=-1;
    121     for (int i=0;i<m;i++)
    122     {
    123         ans=max(ans,dis[col[x[i]]]+rdis[col[y[i]]]);//注意这里是col[x[i]]不要写成x[i]了 
    124         ans=max(ans,rdis[col[x[i]]]+dis[col[y[i]]]);
    125     }
    126     printf("%d",ans-size[1]);
    127 }
    128 
    129 int main()
    130 {
    131     init();
    132     solve();
    133     return 0;
    134 }
  • 相关阅读:
    [转载] 如何更有效地说服开发人员接受你的BUG?
    Coded UI Demo
    等价类划分坐标图
    如何将Excel中的测试用例导入到QC中
    [转载]使用Team Foundation Server(TFS)进行项目Bug管理
    [转载] C# 自定义事件和委托
    TFS Guide
    二叉树的深度优先递归、非递归遍历、广度优先遍历 实例
    部署PHP+Apache+MySQL在Windows实战之例
    NLB的设置 Windows 2008 Server R2
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5911107.html
Copyright © 2020-2023  润新知