C. Longest Simple Cycle

C. Longest Simple Cycle

题意:

有n条链,第i条链上有c[i]个点,a[i]为第i条链的顶点与第i-1条链的连接点,b[i]为第i条链的最后一个点与第i-1条链的连接点。通过上面的方法连接链会产生很多的环,问这些环的最大长度。
看样例

4
3 4 3 3
-1 1 2 2
-1 2 2 3

第二列共4个点,第二列最上面的点连接了第一列的点1(从上往下编号),第二列最下面的点连接了第一列的点2
最后建图得:
在这里插入图片描述

题解:

我们从右往左枚举环的左边界,
假设当前位置在i,当前环包含的点为sum(sum包含环从右边界到i-1位置的上下两个端点,此时还未闭环)
x和y分别记录a[i+1]和b[i+1]的最小值和最大值(即第i列的上下界)
开始分类讨论:
如果x == y,说明这个环结束了(闭环了),必须以i为新的右边界继续进行枚举
如果sum + x + c[i] - y +1 < c[i] 说明以i为新的右边界组成的环一定会大于原有的环(如果左边界在i的左边)。因此我们就舍弃原有的环,以i为右边界继续向左枚举答案
如果sum + x + c[i] - y +1 >= c[i] ,说明当前环比以i为右端点组成的新环更大,因此保留原有环,继续向左枚举。
枚举过程中记录最长闭环的长度

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <bitset>
#include <algorithm>
#define LL long long
#define PII pair<int,int>
#define x first
#define y second
using namespace std;
const int N=1e5+5;
int a[N],b[N],c[N];
int main()
{
    
    
    int t;
	scanf("%d",&t);
	while(t--)
	{
    
    
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%d",&c[i]);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		for(int i=1;i<=n;i++) scanf("%d",&b[i]);
		LL ans=0,sum=0;					//sum表示当前环包含的点数,ans记录环的最大值
		int x=1,y=c[n];					//与上述作用相同
		for(int i=n;i>1;i--)			//从右往左进行枚举
		{
    
    
			if(x==y||sum+x+c[i]-y+1<c[i]) sum=c[i];	//符合条件1,3,以i为新的右边界来组成环,新环的初始长度为c[i]
			else sum+=x+c[i]-y+1;		//符合条件2,继续使用原有环,并更新sum的长度,将i链加入sum
			
			x=min(a[i],b[i]);
			y=max(a[i],b[i]);		//记录新的x,y值
			ans=max(ans,sum+y-x+1);					//记录最大值
		}
		printf("%lld\n",ans); 			//注意,答案有可能爆int
	}
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_35975367/article/details/115017343