zoukankan      html  css  js  c++  java
  • BZOJ5450: 轰炸(水题,Tarjan缩点求最长路)

    5450: 轰炸

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 43  Solved:18
    [Submit][Status][Discuss]

    Description

    有n座城市,城市之间建立了m条有向的地下通道。你需要发起若干轮轰炸,每轮可以轰炸任意多个城市。但每次轰
    炸的城市中,不能存在两个不同的城市i,j满足可以通过地道从城市i到达城市j。你需要求出最少需要多少轮可以
    对每座城市都进行至少一次轰炸。

    Input

    第一行两个整数n,m。接下来m行每行两个整数a,b表示一条从a连向b的单向边。
    n,m<=1000000。

    Output

    一行一个整数表示答案。

    Sample Input

    5 4
    1 2
    2 3
    3 1
    4 5

    Sample Output

    3

    思路:不同的链不会相互影响,所以可以同时炸,显然时间只取决于最长的有向链。我们缩点,然后找最长路即可。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=1000010;
    int Laxt[maxn],Next[maxn],To[maxn],cnt,scc_cnt,head;
    int instk[maxn],q[maxn],dfn[maxn],low[maxn],scc[maxn],times;
    vector<int>G[maxn]; int sz[maxn],dis[maxn],ind[maxn],ans;
    void read(int &x){
        x=0; char c=getchar();
        while(c>'9'||c<'0') c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    }
    void add(int u,int v){
        Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v;
    }
    void tarjan(int u)
    {
        instk[u]=1; q[++head]=u;
        dfn[u]=low[u]=++times;
        for(int i=Laxt[u];i;i=Next[i]){
            int v=To[i];
            if(!dfn[v]) {
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(instk[v])low[u]=min(low[u],dfn[v]);//无向图与有向图的区别
        }
        if(dfn[u]==low[u]){
            scc_cnt++;
            while(true){
                 int x=q[head--];
                 scc[x]=scc_cnt; instk[x]=0; sz[scc_cnt]++;
                 if(x==u) break;
            }
        }
    }
    int main()
    {
        int N,M,u,v; scanf("%d%d",&N,&M);
        rep(i,1,M) read(u),read(v),add(u,v);
        rep(i,1,N) if(!dfn[i]) tarjan(i);
        rep(i,1,N){
            for(int j=Laxt[i];j;j=Next[j]){
                if(scc[i]!=scc[To[j]]){
                    ind[scc[To[j]]]++;
                    G[scc[i]].push_back(scc[To[j]]);
                }
            }
        }
        head=0; int tail=0;
        rep(i,1,scc_cnt) if(!ind[i]) q[++head]=i,dis[i]=sz[i];
        while(tail<head){
            int u=q[++tail];
            ans=max(ans,dis[u]); int L=G[u].size();
            for(int i=0;i<L;i++){
                int v=G[u][i]; ind[v]--;
                dis[v]=max(dis[v],dis[u]+sz[v]);
                if(!ind[v]) q[++head]=v;
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    The Tamworth Two chapter 2.4
    USACO Controlling Companies chapter 2.3 已跪
    非递归快排
    链表二路归并
    Money Systems chapter 2.3 dp
    #pragma pack与sizeof union
    快慢指针
    12
    11
    10
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9964469.html
Copyright © 2011-2022 走看看