QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#654949#7755. Game on a ForestTomgao4116WA 3ms21948kbC++203.1kb2024-10-18 23:07:542024-10-18 23:07:54

Judging History

你现在查看的是最新测评结果

  • [2024-10-18 23:07:54]
  • 评测
  • 测评结果:WA
  • 用时:3ms
  • 内存:21948kb
  • [2024-10-18 23:07:54]
  • 提交

answer

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<long long,long long> pll;
vector<ll> a[500005];
ll vis[500005];
ll cnt[500005]; 
ll sum[500005];
ll pre[500005];
ll f[500005];
ll d[500005];
//每个子树点的异或值:sum[i] 
//子树下面多个子树合并的异或值:pre[i] 
//以点i为根的子树节点个数cnt[i] 
//标号:f[i]:代表第i个点是属于那个点为根的子树:
//标号dfs: 
ll val=0,ans=0; 
void dfs1(ll ver){
	vis[ver]=1;
	for(int i=0;i<a[ver].size();i++){
		ll nxt=a[ver][i];
		if(vis[nxt]==0){
			f[nxt]=f[ver];
			dfs1(nxt);
		}
	}
} 
//预处理dfs 
void dfs2(ll ver){
	cnt[ver]=1;
	pre[ver]=0; 
	vis[ver]=1;
	for(int i=0;i<a[ver].size();i++){
		ll nxt=a[ver][i];
		if(vis[nxt]==0){
			dfs2(nxt);
			cnt[ver]+=cnt[nxt];
			pre[ver]^=sum[nxt];
		}
	}
	//下面子节点个数是奇数:下面sg值为1 
	if(cnt[ver]%2==1){
		sum[ver]=1; 
	//下面子节点个数是偶数:下面sg值为2:	
	}else{
		sum[ver]=2;
	}
}
void dfs3(ll ver,ll root){
	vis[ver]=1;
//	cout<<"ver: "<<ver<<endl;
	for(int i=0;i<a[ver].size();i++){
		ll nxt=a[ver][i];
		if(vis[nxt]==0){
			dfs3(nxt,root);
			ll down=cnt[nxt];
			ll up=cnt[root]-cnt[nxt];
		//	cout<<up<<" "<<down<<" "<<ver<<" "<<nxt<<endl;
			if(down%2==1){
				down=1;
			}else{
				down=2;
			}
			if(up%2==1){
				up=1;
			}else{
				up=2;
			}
		//	cout<<up<<" "<<down<<endl;
			//如果删去这条边后的状态异或和能赢:----代表第二个要输:所以这时候的异或和要为0 对答案的贡献+1; 
			if((val^sum[root]^up^down)==0)ans++;
		}
	}
}
void dfs4(ll ver,ll root){
	vis[ver]=1;
	ll up=cnt[root]-cnt[ver];
	if(up%2==1){
		up=1;
	}else if(up%2==0&&up>0){
		up=2;
	}
//	cout<<"ver: "<<ver<<" "<<up<<endl;
	//如果是最下面叶子节点: 
	if(a[ver].size()==0){
		if(val^sum[root]^up==0)ans++;
	}
	//如果是其他节点: 
	for(int i=0;i<a[ver].size();i++){
		ll nxt=a[ver][i];
		if(vis[nxt]==0){
			dfs4(nxt,root);
			if((val^sum[root]^up^pre[ver])==0){
			//cout<<"ver: "<<ver<<" "<<nxt<<" :"<<val<<" "<<sum[root]<<" "<<up<<" "<<pre[ver]<<endl;
				ans++;
			}
		}
	}
}
int main(){
	ll n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)f[i]=i;
	for(int i=1;i<=m;i++){
		ll u,v;
		cin>>u>>v;
		a[u].push_back(v);
		a[v].push_back(u);
	}
	//dfs:判断每个节点属于哪个子树+做好根节点的标号: 
	for(int i=1;i<=n;i++){
		if(!vis[i]){
			dfs1(i);
		}
	}
	memset(vis,0,sizeof(vis));
	//1:先预处理出树上的前缀异或和+子树节点数目:
	for(int i=1;i<=n;i++){
		//从森林中每个子树的根节点进入dfs预处理: 
	//	cout<<i<<" "<<f[i]<<endl; 
		if(!vis[i]&&f[i]==i){
			dfs2(i);
			if(cnt[i]%2==1){
				val^=1;
			}else{
				val^=2;
			}
		} 	
	}
	//1:枚举删边:
	memset(vis,0,sizeof(vis)); 
	for(int i=1;i<=n;i++){
		if(!vis[i]&&f[i]==i){
			dfs3(i,i);
		}
	}
	//2:枚举删点: 
	memset(vis,0,sizeof(vis)); 
	for(int i=1;i<=n;i++){
		if(!vis[i]&&f[i]==i){
			dfs4(i,i);
		}
	}
	cout<<ans;
	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 15748kb

input:

3 1
1 2

output:

2

result:

ok 1 number(s): "2"

Test #2:

score: 0
Accepted
time: 0ms
memory: 15796kb

input:

4 3
1 2
2 3
3 4

output:

3

result:

ok 1 number(s): "3"

Test #3:

score: -100
Wrong Answer
time: 3ms
memory: 21948kb

input:

100000 1
4647 17816

output:

99999

result:

wrong answer 1st numbers differ - expected: '1', found: '99999'