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;
}

 

posted @ 2019-10-28 22:07  si_nian  阅读(282)  评论(0编辑  收藏  举报