您的位置:首页 > 产品设计 > UI/UE

[SDOI2016]sequence 解题报告

2016-05-17 19:18 543 查看
考场上一直在试图调t3常数。。还有1.5h的时候才看到这个题,感觉是个很麻烦的网络流,强行写想起R1网络流写跪的经历还是写了暴力。。

然而暴力写起来并不比标算好写,考场上写残了好多地方。

要是一上来先切3h这题就好了。。24.

doc题解没认真听。。

说一下我的想法。

最蛋疼的地方在于处理字符串,要先把每行列中回文串删掉。注意到每个行列只有两种选择,这显然是对应网络流中属于S或T。然后每行列建一个点,属于S集表示这一行列中的单词的反串大于原单词,属于T集表示反之。强制属于的就直接与源汇连正无穷。然后每个单词建两个点a,b,之间是容量为1的单向边(a->b),每个有这个单词的行列向a连∞/1,b向行列连∞/1,表示如果有两个行列一个选S一个选T,就必须要割掉1。然后最大流*2+回文串就是答案。

主要是处理字符串比较麻烦。。代码一大半都是在搞字符串。

代码:

#include<cstdio>
#include<iostream>
using namespace std;
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
const int N=72+5;
char a

;
int s[N<<1]
;
string hsh[N*N];
int obj[N*N];
int state[N<<1];

const int V=(N<<1)+(N*N*3);
const int E=(N<<1)+(N*N*3);
const int inf=0x7fffffff;
struct ES{
int from,to,cap;
}e[E<<1];
int etot;
int nxt[E<<1],ptr[V];
int onxt[E<<1],optr[V];
void addedge(int from,int to,int cap){
nxt[etot]=ptr[from],ptr[from]=etot;
onxt[etot]=optr[to],optr[to]=etot;
e[etot++]=(ES){from,to,cap};

//if(cap)printf("addedge(%d,%d,%d)\n",from,to,cap);
}
int q[V],path[V],cur[V],dis[V],gap[V];
int isap(int snk){
int src=snk-1;
memset(dis,127,sizeof(dis));
q[0]=snk,dis[snk]=0;
for(int h=0,t=1;h!=t;++h)
for(int i=optr[q[h]];i;i=onxt[i])
if(e[i].cap&&dis[e[i].from]>1e9)
++gap[dis[q[t++]=e[i].from]=dis[q[h]]+1];
for(int i=snk;i;--i)cur[i]=ptr[i];
if(dis[src]>1e9){
//puts("Discon!");
return 0;
}
for(int ans=0;;){
for(int node=src,i;node!=snk;){
for(i=cur[node];i;i=nxt[i])
if(e[i].cap&&dis[e[i].to]==dis[node]-1){
cur[node]=i;
path[node=e[i].to]=i;
break;
}
if(!i){
if(--gap[dis[node]]==0)return ans;
dis[node]=snk;
for(int i=ptr[node];i;i=nxt[i])
if(e[i].cap&&dis[e[i].to]<dis[node])
dis[node]=dis[e[cur[node]=i].to];
++gap[++dis[node]];
if(node!=src)node=e[path[node]].from;
}
}
for(int node=snk;node!=src;node=e[path[node]].from)--e[path[node]].cap,++e[path[node]^1].cap;
++ans;

//for(int node=snk;node!=src;node=e[path[node]].from)printf("%d ",node);
//printf("%d\n",src);
}
}
int main(){
freopen("sentence.in","r",stdin);
freopen("sentence.out","w",stdout);
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)scanf("%d",state+i);
for(int j=1;j<=m;++j)scanf("%d",state+n+j);
for(int i=1;i<=n;++i)scanf("%s",a[i]+1);

string tmp;
int htot=0;
hsh[0]="";
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j)
if(a[i][j]!='_')hsh[htot]+=a[i][j];
else
if(hsh[htot]!="")
hsh[++htot]="";
if(hsh[htot]!="")hsh[++htot]="";

for(int j=m;j;--j)
if(a[i][j]!='_')hsh[htot]+=a[i][j];
else
if(hsh[htot]!="")
hsh[++htot]="";
if(hsh[htot]!="")hsh[++htot]="";
}
for(int j=1;j<=m;++j){
for(int i=1;i<=n;++i)
if(a[i][j]!='_')hsh[htot]+=a[i][j];
else
if(hsh[htot]!="")
hsh[++htot]="";
if(hsh[htot]!="")hsh[++htot]="";

for(int i=n;i;--i)
if(a[i][j]!='_')hsh[htot]+=a[i][j];
else
if(hsh[htot]!="")
hsh[++htot]="";
if(hsh[htot]!="")hsh[++htot]="";
}
sort(hsh,hsh+htot);
htot=unique(hsh,hsh+htot)-hsh;
for(int i=htot;i--;){
tmp="";
for(int j=hsh[i].size();j--;)tmp+=hsh[i][j];
obj[i]=lower_bound(hsh,hsh+htot,tmp)-hsh;
}

int now=0;
for(int i=htot;i--;)
if(i==obj[i])
++now;
int x;
memset(s,0,sizeof(s));
tmp="";
for(int i=1;i<=n;++i){
//printf("---%d---\n",i);
for(int j=1;j<=m;++j)
if(a[i][j]!='_')tmp+=a[i][j];
else
if(tmp!=""){
x=lower_bound(hsh,hsh+htot,tmp)-hsh;
if(x!=obj[x]){
s[i][++s[i][0]]=x;
//cout<<"Get:"<<tmp<<endl;
}
tmp="";
}
if(tmp!=""){
x=lower_bound(hsh,hsh+htot,tmp)-hsh;
//cout<<x<<endl;
if(x!=obj[x]){
s[i][++s[i][0]]=x;
//cout<<"Get:"<<tmp<<endl;
}
tmp="";
}
}
for(int j=1;j<=m;++j){
for(int i=1;i<=n;++i)
if(a[i][j]!='_')tmp+=a[i][j];
else
if(tmp!=""){
x=lower_bound(hsh,hsh+htot,tmp)-hsh;
if(x!=obj[x])s[n+j][++s[n+j][0]]=x;
tmp="";
}
if(tmp!=""){
x=lower_bound(hsh,hsh+htot,tmp)-hsh;
if(x!=obj[x])s[n+j][++s[n+j][0]]=x;
tmp="";
}
}
n+=m;
for(int i=1;i<=n;++i)
if(s[i][1]>obj[s[i][1]]){
state[i]=-state[i];
for(int j=s[i][0];j;--j)s[i][j]=obj[s[i][j]];
}

/*printf("hsh:");
for(int i=0;i<htot;++i)cout<<hsh[i]<<" ";
puts("");
for(int i=1;i<=n;++i){
printf("%d(%d):",i,state[i]);
for(int j=1;j<=s[i][0];++j)printf("%d ",s[i][j]+1);
puts("");
}*/

etot=2;
memset(ptr,0,sizeof(ptr)),memset(optr,0,sizeof(optr));
int src=n+1+(htot<<1),snk=n+1+(htot<<1)+1;
for(int i=1;i<=n;++i){
if(state[i]==1){
addedge(src,i,inf);
addedge(i,src,0);
}
else if(state[i]==-1){
addedge(i,snk,inf);
addedge(snk,i,0);
}
for(int j=s[i][0];j;--j){
addedge(i,n+1+s[i][j],1);
addedge(n+1+s[i][j],i,0);

addedge(n+1+s[i][j]+htot,i,1);
addedge(i,n+1+s[i][j]+htot,0);
}
}
for(int i=htot;i--;){
addedge(n+1+i,n+1+i+htot,1);
addedge(n+1+i+htot,n+1+i,0);
}
printf("%d\n",now+(isap(snk)<<1));
}
}


总结:

①考试的时候一定要多想想再写:错误、正确性、怎么样写简单。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: