• [JOISC 2016 Day 3] 电报


    一、题目

    点此看题

    二、解法

    最后形成的强联通分量肯定是一个环,每个点的出度一直为 (1),那么我们只要让入度也都为 (1) 即可。

    每个点保留权值最大的入边,其他入边贪心断开即可。

    但是这样还有问题,操作过后可能会形成若干个环,我们要把这些小环接成一个大环。那么一个环上至少满足一个点他断开了环边,所以我们处理出非环边的最大权值,然后贪心地看替换环上哪个点最好即可。

    注意特判整张图是一个大环的情况,时间复杂度 (O(n))

    三、总结

    这个贪心实在是太简洁了,我觉得它的本质是拆分,把最后是一个环这种大限制拆成了每个点入度为 (1) 的小限制,只考虑单点是非常容易的(我觉得单点限制优于整体限制),再考虑例外来修正我们的限制转化即可。

    ( t UPD 2021/11/18):我觉得这道题就是构造答案下界,你会发现每一步都是必要的。

    #include <cstdio>
    #include <iostream>
    using namespace std;
    const int M = 100005;
    #define int long long
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,ans,a[M],c[M],mx[M],cl[M],vis[M];
    signed main()
    {
    	n=read();
    	for(int i=1;i<=n;i++)
    	{
    		a[i]=read();c[i]=read();
    		ans+=c[i];
    	}
    	for(int i=1;i<=n;i++)
    		if(vis[i]==0)
    		{
    			int x=0,y=0,cnt=0;
    			for(x=i;vis[x]==0;x=a[x]) vis[x]=i;
    			if(vis[x]==i)//have this kind of color
    			{
    				for(y=x;vis[y]!=-1;y=a[y])
    					vis[y]=-1,cnt++;//cycle tag
    			}
    			if(cnt==n) {puts("0");return 0;}
    		}
    	for(int i=1;i<=n;i++)
    	{
    		mx[a[i]]=max(mx[a[i]],c[i]);
    		if(vis[i]!=-1) cl[a[i]]=max(cl[a[i]],c[i]);
    	}
    	for(int i=1;i<=n;i++)
    		ans-=mx[i];
    	for(int i=1;i<=n;i++)
    		if(vis[i]==-1)
    		{
    			int mi=1e9;
    			for(int x=i;vis[x]==-1;x=a[x])
    				mi=min(mi,mx[x]-cl[x]),vis[x]=0;
    			ans+=mi;
    		}
    	printf("%lld
    ",ans);
    }
    
  • 相关阅读:
    无责任Windows Azure SDK .NET开发入门篇二[使用Azure AD 进行身份验证]
    无责任Windows Azure SDK .NET开发入门篇一[Windows Azure开发前准备工作]
    了解ASP.NET5 Web应用程序结构
    Hello ASP.NET5
    CentOS7 防火墙 firewall-cmd
    C# 中使用WebClient 请求 https
    使用 gridfs-stream 存储文件遇到的一个坑。
    overflow的几个坑
    IIS7启用静态压缩
    创建高性能移动 web 站点【转载】
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/15017682.html
Copyright © 2020-2023  润新知