zoukankan      html  css  js  c++  java
  • [HNOI2019]校园旅行

    题目

    过于神仙啊,抄题解.jpg

    首先(n)并不是很大啊,我们可以直接用(f_{i,j})表示(i)(j)是否存在一个回文路径

    对于一条回文路径,如果在两端分别添加一个相同的字符,那么仍然是一个回文路径,于是我们可以利用这个来打一个暴力(bfs)

    就像这样

    while(!q[0].empty()) {
    		int x=q[0].front(),y=q[1].front();
    		q[0].pop(),q[1].pop();
    		for(re int i=0;i<v[x].size();i++)
    			for(re int j=0;j<v[y].size();j++) {
    				int xx=v[x][i],yy=v[y][j];
    				if(xx>yy) std::swap(xx,yy);
    				if(S[xx]!=S[yy]||f[xx][yy]) continue;
    				f[xx][yy]=dp[xx][yy]=1;
    				q[0].push(xx),q[1].push(yy);
    			}
    	}
    

    非常显然这个复杂度一点也不科学,卡满就是(O(m^2))的,肯定是要(T)

    但是(n)却不是很大,能不能让边数减小一点呢

    之后就不会啦,愉快地抄题解

    首先我们注意到一个问题,就是我们只需要关注奇偶性就好了,因为我们可以来回走一条边使得长度增加,但是并不能改变奇偶性

    之后我也不知道为什么通过这一点就想到了二分图

    我们把边分成两类,一类是连接相同颜色点的边,一类是连接不同颜色点的边

    我们考虑一个连通块,这个连通块仅由相同颜色的点构成,显然这个连通块里的边都是第一类边

    如果这个连通块是一个二分图,由于二分图不存在奇环,对于任意两个点,所有连接这两个点的路径的奇偶性都是一样的

    由于我们也只关注奇偶性,所以只需要对这个二分图搞出来一棵生成树即可

    如果这个联通块不是一个二分图,那么就一定存在至少一个奇环,那么我们就可以通过走这个奇环使得路径的奇偶性改变

    我们需要让边的数量尽量少,那么只需要求出来一棵有奇环的基环树即可

    这些我们都能通过(dfs)来完成

    对于第二类边,只考虑这些边的话整张图就是一个二分图,于是我们还是对这些边求一个生成树即可

    最后我们发现我们这张图的边数已经和(n)同级了,于是我们直接上最开始的那个暴力,复杂度就是(O(n^2))

    代码

    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define re register
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    const int maxn=5e3+5;
    std::vector<int> v[maxn];
    std::queue<int> q[2];
    struct E{int v,nxt;}e[1000005];
    int n,m,Q,num,tot,flag;
    char S[maxn];
    int f[maxn][maxn],dp[maxn][maxn],vis[maxn],fa[maxn],sz[maxn],pre[maxn];
    int head[maxn],a[500005],b[500005];
    inline void add(int x,int y) {
    	e[++num].v=y;e[num].nxt=head[x];head[x]=num;
    }
    void dfs(int x,int fa) {
    	vis[x]=1;
    	for(re int i=head[x];i;i=e[i].nxt) {
    		if(S[e[i].v]!=S[x]||fa==e[i].v) continue;
    		if(vis[e[i].v]&&S[e[i].v]==S[x]&&!flag) {
    			if(!(pre[e[i].v]^pre[x])) 
    				v[x].push_back(e[i].v),v[e[i].v].push_back(x),flag=1;
    			continue;
    		}
    		v[x].push_back(e[i].v);v[e[i].v].push_back(x);
    		pre[e[i].v]=pre[x]^1;dfs(e[i].v,x);
    	}
    }
    inline int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
    inline void merge(int x,int y) {
    	if(sz[x]<sz[y]) fa[y]=x,sz[y]+=sz[x];
    		else fa[x]=y,sz[x]+=sz[y];
    }
    int main() {
    	n=read(),m=read(),Q=read();scanf("%s",S+1);
    	for(re int x,y,i=1;i<=m;i++) {
    		x=read(),y=read(),add(x,y),add(y,x);
    		if(S[x]!=S[y]) a[++tot]=x,b[tot]=y;
    	}
    	for(re int i=1;i<=n;i++) {
    		if(vis[i]) continue;
    		flag=0;dfs(i,0);
    	}
    	for(re int i=1;i<=n;i++) fa[i]=i,sz[i]=1;
    	for(re int i=1;i<=tot;i++) {
    		int xx=find(a[i]),yy=find(b[i]);
    		if(xx==yy) continue;
    		merge(xx,yy);
    		v[a[i]].push_back(b[i]);
    		v[b[i]].push_back(a[i]);
    	}
    	for(re int i=1;i<=n;i++) f[i][i]=dp[i][i]=1,q[0].push(i),q[1].push(i);
    	for(re int i=1;i<=n;i++) 
    		for(re int j=0;j<v[i].size();j++) {
    			int x=i,y=v[i][j];
    			if(x>y) std::swap(x,y);
    			if(S[x]!=S[y]||f[x][y]) continue;
    			f[x][y]=dp[x][y]=1,q[0].push(x),q[1].push(y);
    		}
    	while(!q[0].empty()) {
    		int x=q[0].front(),y=q[1].front();
    		q[0].pop(),q[1].pop();
    		for(re int i=0;i<v[x].size();i++)
    			for(re int j=0;j<v[y].size();j++) {
    				int xx=v[x][i],yy=v[y][j];
    				if(xx>yy) std::swap(xx,yy);
    				if(S[xx]!=S[yy]||f[xx][yy]) continue;
    				f[xx][yy]=dp[xx][yy]=1;
    				q[0].push(xx),q[1].push(yy);
    			}
    	}
    	for(re int x,y,i=1;i<=Q;i++) {
    		x=read(),y=read();
    		if(x>y) std::swap(x,y);
    		puts(dp[x][y]?"YES":"NO");
    	}
    	return 0;
    }
    
  • 相关阅读:
    2. 商城项目完整购物链路 lq
    如何看源码? lq
    事务的了解 lq
    1. 商城业务架构分析 lq
    并发的基础知识 lq
    mysql 索引 lq
    mysqlinnodb了解 lq
    IE6.0、IE7.0 与FireFox CSS兼容的解决方法
    CSS:html/css教程:背景图片的定位问题详解
    IE6 BUG
  • 原文地址:https://www.cnblogs.com/asuldb/p/10803482.html
Copyright © 2011-2022 走看看