191005CSP模擬題解

T1:對於每條邊,求刪了這條邊原圖能否成爲二分圖,點邊規模2e6
解法:首先判掉無奇環和一個奇環的情況
一條邊合法當且僅當其屬於所有奇環的交集且不屬於任何一個偶環(會構成新的奇環)
那就弄個dfs樹,對於每條返祖邊樹上差分一下,奇環+1偶環-1,最後看差分值是否爲奇環個數即可

Code:

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int res=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
	return res*f;
}
const int N=2e6+5;
int vis[N<<1],head[N<<1],nxt[N<<1],tot=1;
inline void add(int x,int y){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
int dep[N],pt[N],f[N],cnt,tmp;
void dfs(int v,int fa){
	pt[v]=1;
	for(int i=head[v];i;i=nxt[i]){
		if(i==(fa^1)) continue;
		int y=vis[i];
		if(!pt[y]) dep[y]=dep[v]+1,dfs(y,i),f[v]+=f[y];
		else{
			if(dep[y]>dep[v]) continue;
			if((dep[v]-dep[y]+1)&1) ++f[v],--f[y],++cnt,tmp=i>>1;
			else --f[v],++f[y];
		}
	}
}
int ans[N],cntans=0;
inline void dfs2(int v,int fa){
	pt[v]=1;
	if(f[v]==cnt) ans[++cntans]=fa>>1;
	for(int i=head[v];i;i=nxt[i]) if(!pt[vis[i]]) dfs2(vis[i],i);
}
int main(){
	int n=read(),m=read();
	for(int x,y,i=1;i<=m;i++){
		x=read(),y=read();
		add(x,y);add(y,x);
	}
	for(int i=1;i<=n;i++) if(!pt[i]) dep[i]=1,dfs(i,0);
	if(!cnt){
		cout<<m<<"\n";
		for(int i=1;i<=m;i++) cout<<i<<" ";
		return 0; 
	}
	memset(pt,0,sizeof(pt));
	for(int i=1;i<=n;i++) if(!pt[i]) dfs2(i,0);
	if(cnt==1) ans[++cntans]=tmp;
	sort(ans+1,ans+cntans+1);
	cout<<cntans<<"\n";
	for(int i=1;i<=cntans;i++) cout<<ans[i]<<" "; 
	return 0;
}

T2:一個字符串和一個數組,數組某一位的值表示一個字符串的後綴,支持在前端插入一個字符,單點修改數組內某個位置的值,查詢數組某個區間內的所有後綴中字典序最小的
解法:顯然後綴平衡樹,順便%一發zxyoi考場現推後綴平衡樹模板AC
其實可以把串倒過來,然後線段樹維護數組每個位置,區間求min,min的比較用二分哈希即可,nlog2nnlog^2n但可能會被卡常

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int res=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
	return res*f;
}
const int N=2e6+5;
int vis[N<<1],head[N<<1],nxt[N<<1],tot=1;
inline void add(int x,int y){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
int dep[N],pt[N],f[N],cnt,tmp;
void dfs(int v,int fa){
	pt[v]=1;
	for(int i=head[v];i;i=nxt[i]){
		if(i==(fa^1)) continue;
		int y=vis[i];
		if(!pt[y]) dep[y]=dep[v]+1,dfs(y,i),f[v]+=f[y];
		else{
			if(dep[y]>dep[v]) continue;
			if((dep[v]-dep[y]+1)&1) ++f[v],--f[y],++cnt,tmp=i>>1;
			else --f[v],++f[y];
		}
	}
}
int ans[N],cntans=0;
inline void dfs2(int v,int fa){
	pt[v]=1;
	if(f[v]==cnt) ans[++cntans]=fa>>1;
	for(int i=head[v];i;i=nxt[i]) if(!pt[vis[i]]) dfs2(vis[i],i);
}
int main(){
	int n=read(),m=read();
	for(int x,y,i=1;i<=m;i++){
		x=read(),y=read();
		add(x,y);add(y,x);
	}
	for(int i=1;i<=n;i++) if(!pt[i]) dep[i]=1,dfs(i,0);
	if(!cnt){
		cout<<m<<"\n";
		for(int i=1;i<=m;i++) cout<<i<<" ";
		return 0; 
	}
	memset(pt,0,sizeof(pt));
	for(int i=1;i<=n;i++) if(!pt[i]) dfs2(i,0);
	if(cnt==1) ans[++cntans]=tmp;
	sort(ans+1,ans+cntans+1);
	cout<<cntans<<"\n";
	for(int i=1;i<=cntans;i++) cout<<ans[i]<<" "; 
	return 0;
}

T3:雅禮WC2019集訓traffic

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章