• 洛谷 P3489 [POI2009]WIE-Hexer(二进制状压,分层图最短路)


    传送门


    解题思路

    先吐槽一下某谷翻译能不能把输入格式也翻译一下,感觉输入格式比题目描述都长。。


    观察到p非常小,于是考虑状态压缩,将当前能打的怪物压缩成一个二进制数。

    按照每个二进制数分层,一共分得 2^13=8192 层。

    边全部存下会MLE,所以考虑在转移的时候判断一下,只有出边的状态是现在状态的子集时才进行转移。

    AC代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    using namespace std;
    const int maxn=2e6+5;
    const int maxm=1e4+5;
    int cnt,n,m,k,p[maxn],P,dis[maxn],value[maxn];
    struct node{
    	int v,next,w,f;
    }e[maxm];
    void insert(int u,int v,int w,int f){
    	cnt++;
    	e[cnt].v=v;
    	e[cnt].w=w;
    	e[cnt].f=f;
    	e[cnt].next=p[u];
    	p[u]=cnt;
    }
    void dij(){
    	set<pair<int,int> > s;
    	dis[value[0]*n]=0;
    	s.insert(make_pair(0,value[0]*n));
    	while(!s.empty()){
    		int id=s.begin()->second;
    		s.erase(s.begin());
    		int state=id/n;
    		int u=id%n;
    		if(u==n-1){
    			cout<<dis[id]<<endl;
    			return;
    		}
    		for(int i=p[u];i!=-1;i=e[i].next){
    			if((e[i].f&state)!=e[i].f) continue;
    			int v=e[i].v;
    			v=(state|value[v])*n+v;
    			if(dis[v]>dis[id]+e[i].w){
    				s.erase(make_pair(dis[v],v));
    				dis[v]=dis[id]+e[i].w;
    				s.insert(make_pair(dis[v],v));
    			}
    		}
    	}
    	cout<<-1;
    }
    template<class T>inline void read(T &x)
    {
        x=0;register char c=getchar();register bool f=0;
        while(!isdigit(c))f^=c=='-',c=getchar();
        while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
        if(f)x=-x;
    }
    int main(){
    	ios::sync_with_stdio(false);
    	memset(p,-1,sizeof(p));
    	memset(dis,0x3f,sizeof(dis));
    	read(n);read(m);read(P);read(k);
    	for(int i=1;i<=k;i++){
    		int w,q;
    		read(w);read(q);
    		w--;
    		while(q--){
    			int k;
    			read(k);
    			value[w]|=(1<<(k-1));
    		}
    	}
    	for(int i=1;i<=m;i++){
    		int u,v,w,q,res=0;
    		read(u);read(v);read(w);read(q);
    		u--;v--;
    		while(q--){
    			int x;
    			read(x);
    			res|=(1<<(x-1));
    		}
    		insert(u,v,w,res);
    		insert(v,u,w,res);
    	}
    	dij();
    	return 0;
    }
    
  • 相关阅读:
    Number Sequence ----HDOJ 1711
    B. Berland Bingo
    迷宫城堡--HDOJ 1269(Tarjan)
    迷宫城堡--HDOJ 1269
    前向星,链式前向星
    linux下建立无线wifi------简单实用!
    leetcode187- Repeated DNA Sequences- medium
    leetcode173- Binary Search Tree Iterator- medium
    leetcode170- Two Sum III
    leetcode167- Two Sum II
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/15348464.html
Copyright © 2020-2023  润新知