[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+回文串就是答案。
主要是处理字符串比较麻烦。。代码一大半都是在搞字符串。
代码:
总结:
①考试的时候一定要多想想再写:错误、正确性、怎么样写简单。
然而暴力写起来并不比标算好写,考场上写残了好多地方。
要是一上来先切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)); } }
总结:
①考试的时候一定要多想想再写:错误、正确性、怎么样写简单。
相关文章推荐
- iOS开发中如何在UITextView中添加默认文字
- uinty本地图片的读取和剪裁
- Git Gui for Windows的建库、克隆(clone)、上传(push)、下载(pull)、合并
- Spark SQL下的Parquet使用最佳实践和代码实战
- xcodebuild自动化打包失败,返回65
- CI 笔记 easyui 结合后,左侧导航跳转问题
- Android学习之Build.xml文件
- Arithmetic Sequence(dp)
- SPOJ PT07J Query on a tree II
- xcodebuild打包失败返回65
- POJ 1904 King's Quest 强连通分量+二分图增广判定
- 5.UIButton
- xcodebuild命令打包失败解决方法
- easyUI的datagrid实现分页
- 开发时间缩短90% Amaze UI助H5梦工场响应式网站快速上线
- POJ 1986 Distance Queries【LCA】
- 获取手机信息(UIDevice、NSLocale、NSBundle)
- String, StringBuilder, StringBuffer问题
- kendo.ui.Grid绑定单双击事件
- QT中使用QPainter在ui子控件中绘图