2019.10.28 GMOJ 6394 燃烧的火焰
依然是图片题面x
sol:
做法是考虑最大值不变的情况
情况是每个点都存在dist<=mx
对于每个点到燃烧点的距离
如果dist[i][j]<mx 就设那位二进制位1
否则为0
发现所有不合法的情况就是补集的子集
于是离线一下统一枚举,做完了
#pragma GCC optimize("Ofast") #pragma GCC optimize("inline", "fast-math", "unroll-loops", "no-stack-protector") #pragma GCC diagnostic error "-fwhole-program" #pragma GCC diagnostic error "-fcse-skip-blocks" #pragma GCC diagnostic error "-funsafe-loop-optimizations" #include <bits/stdc++.h> using namespace std; int N,M,K; const long long fish=998244353; bool has[1<<21]; long long dis[200005],diss[100005][25],ans; int T[800005],a[200005],cnt,qz[800005],las[800005],nex[800005],Arrive[800005]; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch)) X=(X<<3ll)+(X<<1ll)+(ch^48),ch=getchar(); return w?-X:X; } bool vis[200005]; void SPFA(int S,int K){ memset(dis,63,sizeof(dis)); queue<int> bfs; bfs.push(S); vis[S]=true; dis[S]=0; while (!bfs.empty()){ int Now=bfs.front(); bfs.pop(); vis[Now]=false; for (int i=las[Now];i;i=nex[i]){ if (dis[Arrive[i]]>dis[Now]+qz[i]){ dis[Arrive[i]]=dis[Now]+qz[i]; if (!vis[Arrive[i]]){ vis[Arrive[i]]=true; bfs.push(Arrive[i]); } } } } for (int i=1;i<=N;i++) diss[i][K]=dis[i]; } void jt(int x,int y,int z){ cnt++; nex[cnt]=las[x]; las[x]=cnt; Arrive[cnt]=y; qz[cnt]=z; } long long Pow(long long x,int y){ long long ans=1; for (;y;y>>=1,x=1ll*x*x%fish) if (y&1) ans=1ll*ans*x%fish; return ans; } int main(){ freopen("flame.in","r",stdin); freopen("flame.out","w",stdout); //cout<<Pow(2,12)-1ll*936828929*Pow(2,12)%fish; N=read(),M=read(),K=read(); for (int i=1;i<=K;i++){ T[i]=read(); } for (int i=1;i<=M;i++){ int u,v,w; u=read(),v=read(),w=read(); jt(u,v,w); jt(v,u,w); } for (int i=1;i<=K;i++) SPFA(T[i],i); long long mx=0; for (int i=1;i<=N;i++){ long long mn=diss[i][1]; if (mn==0) mn=diss[i][2]; for (int j=1;j<=K;j++) mn=min(mn,diss[i][j]); mx=max(mx,mn); } int st=(1<<K)-1; for (int i=1;i<=N;i++){ int qwq=0; for (int j=1;j<=K;j++) if (diss[i][j]<=mx) a[i]|=(1<<(j-1)); //a[i]=st^a[i]; has[a[i]]=true; } has[(1<<K)-1]=true; for(int S=1; S<1<<K; ++S) { for(int i=S; i; i^=i&-i) has[S]|=has[S^(i&-i)]; ans+=has[S]; } //ans++; //cout<<ans<<endl; cout<<1ll*(Pow(2,K)-ans+fish)%fish*1ll*Pow(Pow(2,K),fish-2)%fish; return 0; }
干啥啥不行