CF1137C
按照日期把每个博物馆\(i\)拆成\(d\)个点,设\((i,j)\)表示星期\(j\)的第\(i\)个博物馆表示的点,连边:\((i,j)->(to,j\%d+1)\) ,跑一遍\(Tarjan\),再在新图的\(DAG\)上\(dp\)即可
#include <bits/stdc++.h>
#define N 5100100
#define rep(i,x,y) for(i=x;i<=y;++i)
using namespace std;
int head[N],H[N],w[N],a[N],b[N],cnt,d;
int dfn[N],low[N],W[N],num[N],st[N],q[N],dp[N],tmp[N],dep,tot,qwq;
bool vis[N],use[N];
char s[55];
struct ed{
int v,nxt;
}e[N],E[N];
void add(int u,int v){ e[++cnt]=(ed){v,head[u]},head[u]=cnt; }
void ADD(int u,int v){ E[++cnt]=(ed){v,H[u]},H[u]=cnt; }
inline void tarjan(int x){
dfn[x]=low[x]=++tot;
vis[x]=1,st[++dep]=x;
for(int i=head[x];i;i=e[i].nxt){
int to=e[i].v;
if(!dfn[to]){
tarjan(to);
low[x]=min(low[x],low[to]);
} else if(vis[to]) low[x]=min(low[x],dfn[to]);
}
if(dfn[x]==low[x]){
qwq++;int qaq=0;
while(st[dep]!=x){
num[st[dep]]=qwq,vis[st[dep]]=0;
if(w[st[dep]] && !use[st[dep]/(d+1)+1]) W[qwq]+=w[st[dep]],use[st[dep]/(d+1)+1]=1,tmp[++qaq]=st[dep]/(d+1)+1;
st[dep--]=0;
}
num[x]=qwq,vis[x]=0;
if(!use[x/(d+1)+1] && w[x]) W[qwq]+=w[x],use[x/(d+1)+1]=1,tmp[++qaq]=x/(d+1)+1;
st[dep--]=0;
for(int i=1;i<=qaq;++i) use[tmp[i]]=0;
}
}
inline void dfs(int x){
dp[x]=W[x];
for(int i=H[x];i;i=E[i].nxt){
int to=E[i].v;
if(dp[to]==-1) dfs(to);
dp[x]=max(dp[to]+W[x],dp[x]);
}
}
int main(){
int n,m,i,j;
scanf("%d%d%d",&n,&m,&d);
rep(i,1,m) scanf("%d%d",&a[i],&b[i]);
rep(i,1,n){
scanf("\n%s",s+1);
rep(j,1,d) w[(i-1)*(d+1)+j]=s[j]-'0';
}
rep(i,1,m)
rep(j,1,d)
add((a[i]-1)*(d+1)+j,(b[i]-1)*(d+1)+j%d+1);
rep(i,1,n*(d+1)-1) if(!dfn[i]) tarjan(i);
cnt=0;
rep(i,1,n*(d+1)-1)
for(j=head[i];j;j=e[j].nxt)
if(num[i]!=num[e[j].v]) ADD(num[i],num[e[j].v]);
memset(dp,-1,sizeof(dp));
dfs(num[1]);
cout<<dp[num[1]];
}
洛谷P1648
套路题
有这样一个显然的性质$\left| a-b \right|\geq a-b $
然后就枚举每一维的符号,正号为1符号为0,表示成一个二进制数,答案为\(max\{ ans[2^i-1-x]+ans[x]\}\)
详见代码
#include <bits/stdc++.h>
#define N 200005
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
using namespace std;
int x[5],k,p[32],a[32];
int main(){
int n,mx=0;
scanf("%d%d",&n,&k);
memset(p,0xc0,sizeof(p));
for(int i=1;i<=n;++i){
for(int j=0;j<k;++j)
scanf("%d",&x[j]);
for(int i=0;i<(1<<k);++i){
a[i]=0;
for(int j=0;j<k;++j){
int y=(i>>j)&1;
if(y) a[i]+=x[j];
else a[i]-=x[j];
}
}
for(int i=0;i<(1<<k);++i) p[i]=max(a[i],p[i]);
}
for(int i=0;i<(1<<k-1);++i) mx=max(p[i]+p[(1<<k)-i-1],mx);
cout<<mx;
}
CF618G
我的题= = 貌似被大佬们diss了= =
CF1120D
神仙题啊QAQ