luogu P5292 [HNOI2019]校园旅行
生活随笔
收集整理的这篇文章主要介绍了
luogu P5292 [HNOI2019]校园旅行
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
传送门
首先考虑暴力M^2dp,考虑回文串是可以从回文中心每次在两边拓展的,设\(f_{i,j}\)为\(i\)到\(j\)的路径是否是回文串,bfs转移,枚举两点出边,如果两个新端点颜色相同就更新
然后这个大暴力可以优化到70',就是先枚举一端的相邻的点,然后注意到因为固定了那个相邻的点,对应的另一个用来拓展的端点个数是\(O(n)\)的,然后转移是\(O(m)\)的,所以总复杂度为\(O(nm)\)
然后考虑减少边数.对于一个同色的连通块,如果这个连通块是二分图,那么我们只要保留它的一个生成树就好了,因为对于一端在上面的子路径,在生成树上可以使用反复横跳走出同奇偶的子路径(另一边也同理),并且不会影响答案;如果不是二分图,那么就有奇环,有奇环就可以改变路径长度奇偶性,所以在生成树上加一个自环就行了.然后对于每条边两端颜色不同的连通块,显然是二分图,根据上面的道理,保留生成树就行了.然后在新图上跑dp,就是\(O(n^2)\)了
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<vector> #include<cmath> #include<ctime> #include<queue> #include<map> #include<set> #define LL long long #define db doubleusing namespace std; const int N=5000+10,M=500000+10; int rd() {int x=0,w=1;char ch=0;while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}return x*w; } struct graph {int to[M<<1],nt[M<<1],hd[N],tot;void add(int x,int y){++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;} }e,ee; int n,m,q,ff[N]; int findf(int x){return ff[x]==x?x:ff[x]=findf(ff[x]);} bool ng[N][N],co[N],inq[N],bg[N]; int vc[N]; char cc[N]; struct node {int x,y; }; queue<int> qq; queue<node> qu;int main() {e.tot=ee.tot=1;n=rd(),m=rd(),q=rd();scanf("%s",cc+1);for(int i=1;i<=n;++i) ff[i]=i,bg[i]=1,co[i]=cc[i]-'0',ng[i][i]=1,qu.push((node){i,i});for(int i=1;i<=m;++i){int x=rd(),y=rd();e.add(x,y);if(co[x]==co[y]) ff[findf(y)]=findf(x),ng[x][y]=ng[y][x]=1,qu.push((node){x,y});}memset(vc,-1,sizeof(vc));for(int i=1;i<=n;++i)if(findf(i)==i) inq[i]=1,qq.push(i);while(!qq.empty()){int x=qq.front();qq.pop();bool v0=0,v1=0;for(int i=e.hd[x];i;i=e.nt[i]){int y=e.to[i];if(co[x]!=co[y]) continue;if(inq[y]) v0|=!vc[y],v1|=vc[y];else vc[y]=!vc[x],ee.add(x,y),inq[y]=1,qq.push(y);}if(v0&&v1) bg[findf(x)]=0;}for(int i=1;i<=n;++i)if(findf(i)==i&&!bg[i]) ee.add(i,i);for(int i=1;i<=n;++i) ff[i]=i;for(int i=2;i<=e.tot;i+=2){int x=e.to[i],y=e.to[i^1];if(co[x]!=co[y]&&findf(x)!=findf(y)) ee.add(x,y),ff[findf(y)]=findf(x);}while(!qu.empty()){int x=qu.front().x,y=qu.front().y;qu.pop();for(int i=ee.hd[x];i;i=ee.nt[i]){int xx=ee.to[i];for(int j=ee.hd[y];j;j=ee.nt[j]){int yy=ee.to[j];if(co[xx]==co[yy]&&!ng[xx][yy]) ng[xx][yy]=ng[yy][xx]=1,qu.push((node){xx,yy});}}}while(q--) ng[rd()][rd()]?puts("YES"):puts("NO");return 0; }转载于:https://www.cnblogs.com/smyjr/p/10712932.html
总结
以上是生活随笔为你收集整理的luogu P5292 [HNOI2019]校园旅行的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 七、Oracle 数据库设计
- 下一篇: [AT2369] [agc013_c]