• codeforces757F Team Rocket Rises Again【支配树+倍增+拓扑+spfa】


    先跑spfa求出最短路构成的DAG,然后在DAG上跑出支配树dfs出size取max即可
    关于支配树,因为是DAG,支配点就是入点在支配树上的lca,所以一边拓扑一边预处理倍增,然后用倍增求lca

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<vector>
    using namespace std;
    const int N=400005;
    int n,m,s,h[N],cnt,fa[N],sz[N],ans,to[N],si[N],hs[N],de[N],fr[N],b[N],tot,d[N],f[N][20];
    long long dis[N];
    bool v[N];
    vector<int>a[N];
    struct qwe
    {
    	int ne,to,va;
    }e[N<<1];
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void add(int u,int v,int w)
    {
    	cnt++;
    	e[cnt].ne=h[u];
    	e[cnt].to=v;
    	e[cnt].va=w;
    	h[u]=cnt;
    }
    int lca(int x,int y)
    {//cerr<<" "<<x<<" "<<y<<endl;
    	if(de[x]<de[y])
    		swap(x,y);
    	for(int i=18;i>=0;i--)
    		if(de[f[x][i]]>=de[y])
    			x=f[x][i];
    	if(x==y)
    		return x;//cerr<<" "<<x<<" "<<y<<endl;
    	for(int i=18;i>=0;i--)
    		if(f[x][i]!=f[y][i])
    			x=f[x][i],y=f[y][i];//cerr<<x<<"   "<<y<<endl;
    	return f[x][0];
    }
    void dfs(int u)
    {
    	sz[u]=1;
    	for(int i=h[u];i;i=e[i].ne)
    	{
    		dfs(e[i].to);
    		sz[u]+=sz[e[i].to];
    	}
    }
    int main()
    {
    	n=read(),m=read(),s=read();
    	for(int i=1;i<=m;i++)
    	{
    		int x=read(),y=read(),z=read();
    		add(x,y,z),add(y,x,z);
    	}
    	queue<int>q;
    	for(int i=1;i<=n;i++)
    		dis[i]=1e18;
    	dis[s]=0;
    	v[s]=1;
    	q.push(s);
    	while(!q.empty())
    	{
    		int u=q.front();
    		q.pop();
    		v[u]=0;
    		for(int i=h[u];i;i=e[i].ne)
    			if(dis[e[i].to]>dis[u]+e[i].va)
    			{
    				dis[e[i].to]=dis[u]+e[i].va;
    				if(!v[e[i].to])
    				{
    					v[e[i].to]=1;
    					q.push(e[i].to);
    				}
    			}
    	}
    	for(int u=1;u<=n;u++)
    		for(int i=h[u];i;i=e[i].ne)
    			if(dis[e[i].to]+e[i].va==dis[u])
    				a[u].push_back(e[i].to);
    	memset(h,0,sizeof(h));
    	cnt=0;
    	for(int u=1;u<=n;u++)
    		for(int i=0,len=a[u].size();i<len;i++)
    			add(a[u][i],u,0),d[u]++;
    	q.push(s);
    	de[s]=1;
    	while(!q.empty())
    	{
    		int u=q.front();
    		q.pop();
    		b[++tot]=u;
    		if(a[u].size())
    			f[u][0]=a[u][0];//cerr<<u<<"   "<<f[u][0]<<" ";
    		for(int i=1,len=a[u].size();i<len;i++)
    			f[u][0]=lca(f[u][0],a[u][i]);//cerr<<f[u][0]<<endl;
    		de[u]=de[f[u][0]]+1;
    		for(int i=1;i<=18;i++)
    			f[u][i]=f[f[u][i-1]][i-1];
    		for(int i=h[u];i;i=e[i].ne)
    			if(!(--d[e[i].to]))
    				q.push(e[i].to),f[e[i].to][0]=u;
    	}//cerr<<lca(3,6)<<endl;
    	// for(int i=1;i<=n;i++)
    	// {
    		// for(int j=0;j<5;j++)
    			// cerr<<f[i][j]<<" ";
    		// cerr<<endl;
    	// }
    	memset(h,0,sizeof(h));
    	cnt=0;
    	for(int i=1;i<=n;i++)
    		if(f[i][0])
    			add(f[i][0],i,0);//,cerr<<f[i][0]<<" "<<i<<endl;
    	dfs(s);
    	for(int i=1;i<=n;i++)
    		if(i!=s)
    			ans=max(ans,sz[i]);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Android接入WebView
    james邮件服务器部署
    防止网络攻击的方式
    vue开发遇到的问题及解决方式
    jekins和docker的作用
    设计模式(2)[JS版]---JavaScript如何实现单例模式?
    黑客帝国中代码雨如何实现?用 canvas 轻松实现代码雨炫酷效果!
    什么是JavaScript 的闭包???
    纯CSS实现iOS风格打开关闭选择框
    纯CSS实现自定义单选框和复选框
  • 原文地址:https://www.cnblogs.com/lokiii/p/11016973.html
Copyright © 2020-2023  润新知