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

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;
}
posted @ 2024-03-02 23:04  chdy  阅读(5)  评论(0编辑  收藏  举报