codeforces 1093 D. Beautiful Graph(规律)

题目:http://codeforces.com/contest/1093/problem/D

题意:给你一张图,每个点可以填1,2,3 问有多少中填法使得任意两个相邻顶点和为奇数

思路:
第一个点我们填奇数的话有两种 1或3,那么下一个点只能填2,第三个点两种方法… 找到规律,奇数点x,那么方案数为2^x

第一个点填偶数 第二点两种方法 第三个点一种…
偶数点y 方案数2^y
总的方案数为从一个点出发找到奇数点x和偶数点y
2^x + 2^y

我们每搜过一个点,标记该点的奇偶,如果第二次搜到这个点与邻近点奇偶形同说明有奇数环,那么就无解,
注意:这个图可能不是所有点都是连通的,所以要把每个点都搜一遍,答案乘起来

#include<bits/stdc++.h>
#define fi first
#define se second
#define FOR(a) for(int i=0;i<a;i++)
#define sc(a) scanf("%d",&a)
#define show(a) cout<<a<<endl;
#define show2(a,b) cout<<a<<" "<<b<<endl;
#define show3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl;
using namespace std;

typedef long long ll;
typedef pair<int, int> P;
typedef pair<P, int> LP;
const ll inf = 1e17 + 10;
const int N = 3e5 + 10;
const ll mod = 998244353;

map<string, int>ml;



ll b[N], vis[N], po[N],num[N], t, n, m, x, y, k, a[N];
ll ex, ey, cnt, ans, sum, flag;
ll dist[N];
ll dp[N];
deque <int> q;
vector<int> v[N];

void dfs(int u,int cnt)
{
	if(flag) return ;
	if(cnt==1) x++;
	if(cnt==2) y++;
	vis[u]=cnt;
	//show2(u,cnt);
	//show2('x',x);
	//show2('y',y);
	for(int i=0;i<v[u].size();i++)
	{
		int to=v[u][i];
		if(vis[to]==0)
		{
			dfs(to,3-cnt);
		}
		else if(vis[to]==cnt)
		{
			flag=1;
			return;
		}
	}

}

int main()
{
	ios::sync_with_stdio ( false );
	cin.tie ( 0 );

	cin>>t;
	po[0]=1;
	for(int i=1;i<=N;i++)
		po[i]=(po[i-1]*2)%mod;
	while(t--)
	{
		cin>>n>>m;
		flag=0;
		ans=1;

		for(int i=1;i<=m;i++)
		{
			cin>>x>>y;
			v[y].push_back(x);
			v[x].push_back(y);
		}
		for(int i=1;i<=n;i++)
		{
			if(!vis[i])
			{
				x=0;
				y=0;
				dfs(i,1);
				ans=ans*(po[x]+po[y])%mod;
			}
		}



		for(int i=1;i<=n;i++)
		{
			v[i].clear();
			vis[i]=0;
		}
		if(flag)
		{
			cout<<0<<endl;
		}
		else cout<<ans<<endl;
	}



}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值