zoukankan      html  css  js  c++  java
  • [题解]luogu_P3119草鉴定(分层图

    如果考虑没有逆行操作的时候,我们想到缩点,然后在DAG图上随便就能搞出来,加入逆行操作后:(在DAG图上)

    1.逆行操作相当于把DAG图的一条边变成无向边走两次,所以可以考虑分层图

    先复制一层图,编号n+1~n+n,对于每个原图中的点向所有指向它的边建一条反边指向另外一层,表示我可以从这个点逆行到下一层,而下一层全部是逆行后的状态,无法回到上一层,这样把点的size当做边权跑最长路就正确了

    2.乱搞

    分别预处理出以1号点为起点和终点的最长路dis1,dis2,逆行所产生的效果是这样的:

    这样答案显然对于边x->y,答案为$dis1[y]+dis2[x]pmsize[1]$(根据计算dis时包不包含1号点size决定),且dis1[y]、dis2[x]不为0(即可达)

    题解里还有拆1号点拓扑排序的做法也很好

    代码:

    1.我不知道为什么但我的spfa真的T了.....WDMND(GKNMLGB

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int maxn=100009;
    inline int read(){
        register int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return (f==1)?x:-x;
    }
    int n,m,tot;
    struct node{
        int v,nxt;
    }e[maxn],ed[maxn];
    int head[maxn],cnt,head2[maxn],cnt2;
    inline void add(int u,int v){
        e[++cnt].v=v;e[cnt].nxt=head[u];head[u]=cnt;
    }
    inline void add2(int u,int v){
        ed[++cnt2].v=v;ed[cnt2].nxt=head2[u];head2[u]=cnt2;
    }
    int tim,top,s;
    int vis[maxn],stac[maxn],id[maxn],siz[maxn<<1],low[maxn],dfn[maxn];
    bool v[maxn<<1];
    void tarjan(int x){
        low[x]=dfn[x]=++tim;
        stac[++top]=x;vis[x]=1;
        for(int i=head[x];i;i=e[i].nxt){
            int y=e[i].v;
            if(!dfn[y]){
                tarjan(y);
                low[x]=min(low[x],low[y]);
            }
            else if(vis[y]) low[x]=min(low[x],low[y]);
        }
    //    if(dfn[x]==low[x]){
    //        int y;tot++;
    //        while(y=stac[top--]){
    //            id[y]=x;
    //            vis[y]=0;
    //            if(x==y)break;
    //            siz[x]+=siz[y];
    //        }
    //    }
        if(dfn[x]==low[x]){
            tot++;
            while(stac[top]!=x){
                id[stac[top]]=tot;
                vis[stac[top]]=0;
                siz[tot]++;
                top--;
            }
            id[stac[top]]=tot;
            vis[stac[top]]=0;
            siz[tot]++;
            top--;
        }
    }
    queue<int>q;
    int dis[maxn<<1];
    void spfa(){
        q.push(id[1]);v[id[1]]=1;
        while(!q.empty()){
            int x=q.front();q.pop();v[x]=0;
            for(int i=head2[x];i;i=ed[i].nxt){
                int y=ed[i].v;
                if(dis[y]<dis[x]+siz[x]){
                    dis[y]=dis[x]+siz[x];
                    if(!v[y])q.push(y),v[y]=1;
                }
            }
        }
    }
    int main(){
        freopen("testdata (2).in","r",stdin);
        n=read(),m=read();
    //    for(int i=1;i<=n;i++)siz[i]=1;
        for(int i=1,u,v;i<=m;i++){
            u=read(),v=read();
            add(u,v);
        }
        for(int i=1;i<=n;i++)
        if(!dfn[i])tarjan(i);
        for(int i=1;i<=tot;i++)siz[i+tot]=siz[i];
        for(int x=1;x<=n;x++)
        for(int i=head[x];i;i=e[i].nxt){
            int y=e[i].v;
            if(id[x]==id[y])continue;
            add2(id[x],id[y]);
            add2(id[y],id[x]+tot);//加两层之间的边 
            add2(id[x]+tot,id[y]+tot);//加第二层的边 
        }
        spfa();
        printf("%d
    ",dis[id[1]+tot]);
    }
  • 相关阅读:
    LeetCode Power of Three
    LeetCode Nim Game
    LeetCode,ugly number
    LeetCode Binary Tree Paths
    LeetCode Word Pattern
    LeetCode Bulls and Cows
    LeeCode Odd Even Linked List
    LeetCode twoSum
    549. Binary Tree Longest Consecutive Sequence II
    113. Path Sum II
  • 原文地址:https://www.cnblogs.com/superminivan/p/11456009.html
Copyright © 2011-2022 走看看