zoukankan      html  css  js  c++  java
  • [USACO15JAN]草鉴定Grass Cownoisseur (分层图,最长路,$Tarjan$)

    题目链接


    Solution

    水水的套路题。
    可以考虑到一个环内的点是可以都到达的,所以 (tajan) 求出一个 (DAG)
    然后 (DAG) 上的点权值就是 (scc) 的大小。
    对于那条可以反的边,直接建两层图就好了。
    最后跑最长路,第一个节点的 (scc) 在第二张图上的对应节点的答案即为答案。

    Code

    #include<bits/stdc++.h>
    #define N 200008
    #define in(x) x=read()
    using namespace std;
    
    int read()
    {
    	char ch=getchar();int f=1,w=0;
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();}
    	return f*w;
    }
    
    struct sj{int fr,to,next,w;}a[N*4];
    int dfn[N],low[N],cnt;
    int bl[N],siz[N];
    int head[N],size,n,m;
    int sta[N],top,v[N],tot,dis[N];
    
    void add(int x,int y,int w)
    {
    	a[++size].to=y;
    	a[size].fr=x;
    	a[size].next=head[x];
    	head[x]=size;
    	a[size].w=w;
    }
    
    void tarjan(int x)
    {
        dfn[x]=low[x]=++tot;
        sta[++top]=x; v[x]=1;
        for(int i=head[x];i;i=a[i].next)
        {
        	int tt=a[i].to;
            if(!dfn[tt]){
                tarjan(tt);
                low[x]=min(low[x],low[tt]);
            }
            else if(v[tt]) low[x]=min(low[x],dfn[tt]);
        }
        if(dfn[x]==low[x])
        {
            v[x]=0; 
            bl[x]=++cnt;
            do{
            	siz[cnt]++;
                v[sta[top]]=0;
                bl[sta[top]]=cnt;
            }while(sta[top--]!=x);
        }
    }
    
    void SPFA()
    {
    	memset(v,0,sizeof(v));
    	int s=bl[1],t=bl[1]+cnt;
    	queue<int>q; q.push(s); v[s]=1; dis[s]=0;
    	while(!q.empty())
    	{
    		int x=q.front();q.pop();v[x]=0;
    		for(int i=head[x];i;i=a[i].next)
    		{
    			int tt=a[i].to;
    			if(dis[tt]<dis[x]+a[i].w)
    			{
    				dis[tt]=dis[x]+a[i].w;
    				if(!v[tt]) q.push(tt),v[tt]=1;
    			}
    		}	
    	}
    	printf("%d",dis[bl[1]+cnt]);
    }
    
    int main()
    {
    	in(n),in(m);
    	for(int i=1;i<=m;i++)
    	{
    		int x,y; in(x),in(y);
    		add(x,y,0); 
    	}
    	for(int i=1;i<=n;i++)
    	   if(!dfn[i])tarjan(i);
         
        memset(head,0,sizeof(head));  
    	for(int i=1;i<=m;i++)
    	{
    		int tt=a[i].to,fr=a[i].fr;
    		if(bl[tt]!=bl[fr])
    		{
    			add(bl[fr],bl[tt],siz[bl[fr]]);
    			add(bl[fr]+cnt,bl[tt]+cnt,siz[bl[fr]]);
    			add(bl[tt],bl[fr]+cnt,siz[bl[tt]]);
    		}
    	}
    	memset(dis,-1,sizeof(dis));
    	SPFA();
    	return 0;
    }
    
  • 相关阅读:
    PAT 甲题 1155 Heap Paths
    PAT甲题 1014 Waiting in Line
    PAT甲题 1014 Waiting in Line
    AcWing 840. 模拟散列表
    2019新生赛 %%%xxh
    AcWing 240. 食物链
    AcWing 143. 最大异或对
    AcWing 838. 堆排序
    AcWing 836. 合并集合
    AcWing 837. 连通块中点的数量
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/9787738.html
Copyright © 2011-2022 走看看