Educational Codeforces Round 56 (Rated for Div. 2) D. Beautiful Graph(二分圖判定+計數)
阿新 • • 發佈:2019-01-12
題意
給一個圖,圖上的點可以被染成權值為1,2,3
令邊權=兩個點的點權和,求令邊權為奇數的所有方案數%998244353
思路來源
自己寫的
題解
首先二分圖判定一下,分奇偶層;
奇層染奇數,偶層染偶數;
或奇層染偶數,偶層染奇數。
對於每個連通分量,其方案數為(modpow(2,奇層點數,MOD)+modpow(2,偶層點數,MOD))%MOD
這個modpow是快速冪。
然後整個圖的就是所有連通分量的乘積%MOD了。
心得
開始沒注意到圖不一定是連通圖,WA了一發。
再後來e陣列60W開小了,又WA一發。
再後來這個n總共是3e5,每次去memset所有,T了五六發……
所以應該就是for迴圈到n賦初值 這樣遭遇T=300000 n=1 m=0的極限樣例也不會爆了
或者每次用到哪個的時候才去初始化哪個,最後就是改成這樣的
程式碼還是不規範啊……明明能O(均攤n),非要O(T·n),
改完之後2000msTLE變140msAC,真是令人窒息的操作
程式碼
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <cmath> #include <set> #include <map> #include <vector> #include <stack> #include <queue> #include <functional> const int INF=0x3f3f3f3f; const int maxn=3e5+10; const int mod=1e9+7; const int MOD=998244353; const double eps=1e-7; typedef long long ll; #define vi vector<int> #define si set<int> #define pii pair<int,int> #define pi acos(-1.0) #define pb push_back #define mp make_pair #define lowbit(x) (x&(-x)) #define sci(x) scanf("%d",&(x)) #define scll(x) scanf("%I64d",&(x)) #define sclf(x) scanf("%lf",&(x)) #define pri(x) printf("%d",(x)) #define rep(i,j,k) for(int i=j;i<=k;++i) #define per(i,j,k) for(int i=j;i>=k;--i) #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; int cnt,head[maxn],color[maxn],shu; int t,n,m,pos[maxn],neg[maxn],now; struct edge { int to,nex; }e[maxn*2]; //可能很多連通分量 最後的答案是各連通分量貢獻的乘積 //二分圖判定一次 void init(int n) { for(int i=0;i<n;++i) color[i]=0,head[i]=-1; cnt=0; shu=1; } void add(int u,int v) { e[cnt].to=v; e[cnt].nex=head[u]; head[u]=cnt++; } ll modpow(ll x,ll n,ll mod) { if(n==0)return 1; ll res=modpow(x,n/2,mod),ans=res*res; if(ans>=mod)ans%=mod; if(n&1)ans=ans*x; if(ans>=mod)ans%=mod; return ans; } bool judge(int u,int c) { color[u]=c; if(c>0)pos[c]++; else { int p=-c; neg[p]++; } for(int i=head[u];~i;i=e[i].nex) { int v=e[i].to; if(color[v]==c)return 0;//相鄰同號 if(color[v]==0&&!judge(v,-c))return 0; } return 1; } ll solve() { ll ans=1; for(int i=0;i<n;++i) { if(color[i]==0) { pos[shu]=0;//memset會T!!! neg[shu]=0;//memset會T!!! if(!judge(i,shu))return 0; shu++; //shu-1個連通分量 } } rep(i,1,shu-1) { ll tmp1=modpow(2,pos[i],MOD); ll tmp2=modpow(2,neg[i],MOD); ll q=tmp1+tmp2; if(q>=MOD)q%=MOD; ans=ans*q; if(ans>=MOD)ans%=MOD; } return ans; } int main() { sci(t); while(t--) { sci(n),sci(m); init(n); rep(i,0,m-1) { int u,v; sci(u),sci(v); u--,v--; add(u,v); add(v,u); } printf("%I64d\n",solve()); } return 0; }