• 7311. 【2021.10.18NOIP提高组模拟】葡萄庄园


    Description

    (nle 10^5,mle 2 imes 10^5)

    Solution

    由于颜色只有 3 个,考虑将图分层。

    统计出不走某个颜色的情况下,每个节点所处的联通块。

    那么改变颜色可以认为是在某个节点同时走两个联通块。

    预处理答案,枚举节点,统计所处的三个联通块两两联通的价值,注意去重(可以用 ( ext{map}),也可以排序)。

    同时维护每个连通块与别的连通块连接的最优情况。

    对于询问的 (x),找出所处的三个连通块中最优情况价值最大的,即为答案。

    Code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 100005
    #define M 200005
    #define ll long long
    using namespace std;
    int n,m,q,x,y,z,tot,num,sum,len,cir[N][5];
    ll a[N],size[N*3],f[N*3];
    struct node
    {
    	int to,next,head,cl;
    }edge[M<<1];
    struct circ
    {
    	int id,x,y;
    	ll v;	
    }c[N*3],d[N*3];
    void add(int x,int y,int z)
    {
    	edge[++tot].to=y;
    	edge[tot].cl=z;
    	edge[tot].next=edge[x].head;
    	edge[x].head=tot;
    }
    void dfs(int x,int c)
    {
    	size[num]+=a[x];
    	for (int i=edge[x].head;i;i=edge[i].next)
    	{
    		int v=edge[i].to;
    		if (edge[i].cl==c) continue;
    		if (cir[v][c]) continue;
    		cir[v][c]=num;
    		dfs(v,c);
    	}
    }
    bool cmp(circ x,circ y)
    {
    	if (x.x<y.x) return true;
    	if (x.x>y.x) return false;
    	return x.y<y.y;
    }
    int main()
    {
    	freopen("grape.in","r",stdin);
    	freopen("grape.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;++i)
    		scanf("%lld",&a[i]);
    	for (int i=1;i<=m;++i)
    	{
    		scanf("%d%d%d",&x,&y,&z);
    		add(x,y,z);add(y,x,z);
    	}
    	for(int j=1;j<=3;++j)
    		for (int i=1;i<=n;++i)
    			if (!cir[i][j]) cir[i][j]=++num,dfs(i,j);
    	for (int i=1;i<=n;++i)
    	{
    		x=cir[i][1];y=cir[i][2];z=cir[i][3];
    		c[++sum].x=x;c[sum].y=y;c[sum].v=size[x]+size[y],c[sum].id=i;
    		c[++sum].x=x;c[sum].y=z;c[sum].v=size[x]+size[z],c[sum].id=i;
    		c[++sum].x=y;c[sum].y=z;c[sum].v=size[y]+size[z],c[sum].id=i;
    	}
    	sort(c+1,c+sum+1,cmp);
    	for (int i=1;i<=sum;++i)
    	{
    		if (c[i].x!=c[i-1].x||c[i].y!=c[i-1].y)
    		{
    			if (len) f[d[len].x]=max(f[d[len].x],d[len].v),f[d[len].y]=max(f[d[len].y],d[len].v);
    			d[++len].x=c[i].x;
    			d[len].y=c[i].y;
    			d[len].v=c[i].v-a[c[i].id];
    		}
    		else d[len].v-=a[c[i].id];
    	}//去重并统计答案
    	scanf("%d",&q);
    	while (q--)
    	{
    		scanf("%d",&x);
    		printf("%lld
    ",max(max(f[cir[x][1]],f[cir[x][2]]),f[cir[x][3]]));
    	}
    	return 0;
    } 
    
    
  • 相关阅读:
    java ssh整合报错:java.lang.NoSuchMethodError: antlr.collections.AST.getLine()I
    Ubuntu16.04安装搜狗输入法后有黑边问题的解决方法
    socket
    vim编辑器的使用
    linux用户和群组
    bash shell
    [LightOJ 1128]Greatest Parent
    [Luogu P4180][BJWC 2010]严格次小生成树
    函数、方法区别
    有关_meta内容(持续更新)
  • 原文地址:https://www.cnblogs.com/Livingston/p/15428025.html
Copyright © 2020-2023  润新知