2018-8-13队测

**T1** ![](https://images2018.cnblogs.com/blog/1330553/201808/1330553-20180814111033738-1273496784.png) 一开始想拿40分的暴力分 直接暴力求出cnt[i]为出现过i次的串有多少个 然后对于k=2,答案为 $$\sum_{i=1}^{m}cnt[i]cnt[m-i]$$ 复杂度$O(n^3+kn^2)$

然后正解就很显然了
直接拿后缀自动机求出cnt数组
然后后面的式子是一个卷积形式,拿ntt快速幂算就可以了

无奈我后缀自动机不会。。有时间在学吧。。

T2

这题好像在省队集训讲过。。

这题30分dp很显然

\[f[i][j]=min(f[i-1][j-1],f[i-1][j])+v[j] \]

100分好像要计算几何。。题解没看懂。。

T3

考完之后发现是bzoj原题。。
题号4177
部分分直接枚举每一位选a还是选b,30分

正解考场上想到了,然而无奈码力太差,没调出来。。
正解网络流
建完图后用sum减去最小割
就是说割掉的边是不要的

然后考虑建图
先考虑选a还是选b
选a就从s向i连一条流量为x的边
否则从i向t连

考虑第一个限制
对于限制i,j
从i向j连一条流量为w的边,注意反向边也为w
这个可以这样理解
如果在同侧割,新建的边就没用了
否则两条中必割一条

然后第二条限制
新建一个点new
如果op==1 s向new连w的边,new向S集合连inf的边
否则 new向t连w的边,S集合向new连inf的边

代码(只有能力改这一题QAQ)

#include<bits/stdc++.h>
#pragma GCC optimize(3)
using namespace std;
#define read(x) scanf("%d",&x)
#define write(x) printf("%d\n",x)
#define maxn 1000050
#define inf INT_MAX
int head[maxn],tot=1,n,m,k,x,y,tt,op,sum,lev[maxn];
struct edge{int to,nxt,w;}e[maxn<<1];
void add(int u,int v,int w){e[++tot].to=v,e[tot].nxt=head[u],head[u]=tot,e[tot].w=w;}
void ins(int u,int v,int w){add(u,v,w),add(v,u,0);}
int bfs(int s,int t){
    memset(lev,-1,sizeof lev);
    queue<int> q;
    q.push(s),lev[s]=0;
    while(!q.empty()){
	int now=q.front();q.pop();
	for(int i=head[now];i;i=e[i].nxt)
	    if(e[i].w>0&&lev[e[i].to]==-1) lev[e[i].to]=lev[now]+1,q.push(e[i].to);
    }
    return lev[t]>0;
}
int dfs(int u,int t,int f){
    if(u==t) return f;
    for(int i=head[u];i;i=e[i].nxt)
	if(lev[e[i].to]>lev[u]&&e[i].w>0){
	    int d=dfs(e[i].to,t,min(e[i].w,f));
	    if(d>0){e[i].w-=d,e[i^1].w+=d;return d;}
	}
    lev[u]=-1;
    return 0;
}
int dinic(int s,int t){
    int f,flow=0;
    while(bfs(s,t)){while((f=dfs(s,t,inf))) flow+=f;}
    return flow;
}
int main(){
    read(n),read(m),read(k);
    int s=0,t=maxn-1;
    for(int i=1;i<=n;i++) read(x),ins(s,i,x),sum+=x;
    for(int i=1;i<=n;i++) read(x),ins(i,t,x),sum+=x;
    for(int i=1;i<=m;i++) read(x),read(y),read(tt),add(x,y,tt),add(y,x,tt);
    for(int i=1;i<=k;i++){
	read(tt),read(op),read(y);sum+=y;
	if(op) ins(n+i,t,y);
	else ins(s,n+i,y);
	for(int j=1;j<=tt;j++)
	    if(op) read(x),ins(x,n+i,inf);
	    else read(x),ins(n+i,x,inf);
    }
    write(sum-dinic(s,t));
    return 0;
}

posted @ 2018-08-14 11:39  Hyscere  阅读(160)  评论(0编辑  收藏  举报