首页 > 其他分享 >牛客练习赛122 F 括号匹配 费用流

牛客练习赛122 F 括号匹配 费用流

时间:2024-03-02 23:11:24浏览次数:17  
标签:练习赛 top add tn 牛客 122 include id define

CF打多了很多题目中的性质都挖掘出来了,也想到了费用流。

很难\(dp\)因为一组中三个括号留下来一个很难作为状态进行dp。

由于对括号匹配还不熟悉以为是\(n^2\)的图就没写了,事实上应该是线性的建图。

所以对于\(n=2000\)这个数据范围网络流是可以过的。

设置源点\(S\)和汇点\(T\)。

对于左括号来说显然是和\(S\)相连,右括号和\(T\)相连。只需要相邻两个之间连边右括号即可简化建图,或者每次遇到一个左括号都虚设一个点来维护前缀点的集合,遇到右括号就连向最近的虚设前缀点,这显然不如前一种方法。

对于限制虚设点来满足即可。

菜就多练。

code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define inf 100000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define putl_(x) printf("%lld ",x);
#define get(x) x=read()
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;i+=1)
#define fep(n,p,i) for(int i=n;i>=p;--i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define sq sqrt	
#define x(w) t[w].x
#define r(w) t[w].r
#define l(w) t[w].l
#define yy p<<1|1
#define zz p<<1
#define sum(w) t[w].sum
#define mod 1000000007
#define sc(A) scanf("%d",&A)
#define scl(A) scanf("%lld",&A)	
#define scs(A) scanf("%s",A);
#define put(A) printf("%d\n",A)
#define min(x,y) (x>=y?y:x)
#define max(x,y) (x>=y?x:y)
#define sub(x,y) (x-y<0?x-y+mod:x-y)
#define F first
#define S second
using namespace std;
//const int MAXN=1<<19;
const int MAXN=1000010;
int n,m,id;
char a[MAXN];
int vis[MAXN];
int w[MAXN];
int S,T,len=1;
int s[MAXN];

int in[MAXN],pre[MAXN],res;
ll dis[MAXN],ans;
int lin[MAXN],ver[MAXN],nex[MAXN],e[MAXN];int e1[MAXN];
inline void add(int x,int y,int z,int z1)
{
	ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;e1[len]=z1;
	ver[++len]=x;nex[len]=lin[y];lin[y]=len;e[len]=0;e1[len]=-z1;
}
int q[MAXN];
inline int spfa()
{
	rep(1,id,i)dis[i]=-inf,vis[i]=0;
	int l=0,r=0;
	q[++r]=S;dis[S]=0;in[S]=INF;
	while(++l<=r)
	{
		int x=q[l];vis[x]=0;
		go(x)
		{
			if(!e[i])continue;
			if(dis[x]+e1[i]>dis[tn])
			{
				dis[tn]=dis[x]+e1[i];
				in[tn]=min(in[x],e[i]);
				pre[tn]=i;
				if(!vis[tn])q[++r]=tn,vis[tn]=1;
			}
		}
	}
	return dis[T]!=-inf;
}
inline void EK()
{
	int x=T,i;
	ans-=dis[T]*in[T];
    res+=in[T];
	while(x!=S)
	{
		i=pre[x];
		e[i]-=in[T];
		e[i^1]+=in[T];
		x=ver[i^1];
	}
}
int main()
{
    //freopen("1.in","r",stdin);
    sc(n);sc(m);
    if(n&1){puts("No");return 0;}
    int ww=n-m*2;ww=ww>>1;
    id=n;S=++id;T=++id;
    scs(a+1);
    rep(1,n,i)sc(w[i]);
    rep(1,m,i)
    {
        int x,y,z;
        sc(x);sc(y);sc(z);
        vis[x]=vis[y]=vis[z]=1;
        ans+=w[x];ans+=w[y];ans+=w[z];
        if(a[x]=='(')
        {
            ++id;
            add(S,id,1,0);
            add(id,x,1,w[x]);
            add(id,y,1,w[y]);
            add(id,z,1,w[z]);
        }
        else
        {
            ++id;
            add(id,T,1,0);
            add(x,id,1,w[x]);
            add(y,id,1,w[y]);
            add(z,id,1,w[z]);
        }
    }
    int top=0;
    rep(1,n,i)
    {
        if(!vis[i])
        {
            if(a[i]=='(')add(S,i,1,0);
            if(a[i]==')')add(i,T,1,0);
        }
        if(a[i]=='(')s[++top]=i;
        else
        {
            while(top)add(s[top],i,1,0),--top;
            if(s[top])add(s[top],i,INF,0);
            s[top]=i;
        }
    }
    while(spfa())EK();
    
    //cout<<res<<endl;

    if(res!=ww)puts("No");
    else
    {
        puts("Yes");
        putl(ans);
    }
    return 0;
}

标签:练习赛,top,add,tn,牛客,122,include,id,define
From: https://www.cnblogs.com/chdy/p/18049432

相关文章

  • 牛客练习赛122 (小白登山记)
    A.黑白配思路:n个学生手心和手背分为2个组求出他们的差直接按题意写即可Code:#include<bits/stdc++.h>usingnamespacestd;intmain(){intn,m;cin>>n>>m;for(inti=0;i<n;++i){intcnt1=0,cnt0=0;for(intj=0......
  • 代码随想录算法训练营第三十二天 | 45.跳跃游戏II ,55. 跳跃游戏,122.买卖股票的最佳时
     122.买卖股票的最佳时机II 已解答中等 相关标签相关企业 给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购......
  • 2024牛客寒假算法基础集训营6 题解 ( A,B,C,D,E,I)
    2024牛客寒假算法基础集训营6题解(A,B,C,D,E,I)A 宇宙的终结题意找到\([l,r]\)区间中有多少数恰好等于三个不同素数的乘积思路数据范围很小,可以考虑暴力,遍历\([l,r]\)区间内每个数,拿每个小于当前数的素数一直往下除,判断是否存在能被恰好3个素数整除的情况代码/********......
  • 2024牛客寒假算法基础集训营5 题解 ( A,C,G,H,I,L,M )
    2024牛客寒假算法基础集训营5题解(A,C,G,H,I,L,M)A mutsumi的质数合数题意有一个由\(n\)个正整数组成的数组,她想知道数组中质数和合数共有几个。思路由质数和合数的定义可知,正整数范围内除\(1\)外,要么是质数要么是合数,本题直接统计不是\(1\)的正整数的个数即可代码......
  • 1224本周补题
    P1142轰炸-洛谷|计算机科学教育新生态(luogu.com.cn)似乎数据有点小,三重循环都能过,也可以整个map然后二次循环枚举最后遍历一次也可以,特别注意的是最开始我枚举的斜率,实际上在题目要求之下需要的是三点共线,只是斜率相等并不能满足题意。#include<bits/stdc++.h>usingnam......
  • 2024牛客寒假算法基础集训营1(补题)
    目录ABCDEFGHIKLAn的范围很小暴力直接\(O(n^3)\)直接做就行。我还傻的统计了一下前后缀,不过怎么写都行这道题。#include<bits/stdc++.h>#defineintlonglong#definerep(i,a,b)for(inti=(a);i<=(b);++i)#definefep(i,a,b)for(inti=(a);i>=(b);--i)#d......
  • 2024牛客寒假算法基础集训营4
    2024牛客寒假算法基础集训营4A 柠檬可乐题意根据给定的\(a\)和\(b\),判断是否\(a\gek\timesb\)思路题意非常直接代码/*******************************|Author:AlwaysBeShine|Problem:柠檬可乐|Contest:NowCoder|URL:https://ac.nowcoder.com/acm/......
  • 牛客周赛 Round 34
    牛客周赛Round34比赛链接感觉比以往难度有些大,但是大佬们该强的还是很强啊小红的字符串生成思路就两个字符,如果字符相同只能组成两种,不同则可以组成四种Code#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#defineall(x)x.begin()+1,x.end()#de......
  • 2024牛客寒假算法基础集训营6 K 错综的统一 题解
    Question2024牛客寒假算法基础集训营6K错综的统一一个矩阵仅由"r",“e”,“d”组成一个矩阵区域是美丽的,当且仅当:在矩形区域内,任意横向或纵向取一个长度大于\(1\)的连续字串是,该字符串都不是回文的现在有\(Q\)次询问,每次给定一个矩阵,问最少修改多少字符(字符只能修改"r"......
  • 牛客周赛34(A~E)
    A两种情况两个字符相同只有2两个字符不相同4#include<bits/stdc++.h>#defineintlonglong#definerep(i,a,b)for(inti=(a);i<=(b);++i)#definefep(i,a,b)for(inti=(a);i>=(b);--i)#definepiipair<int,int>#definepddpair<double,double......