zoukankan      html  css  js  c++  java
  • [hdu6166]Senior Pan——顶点集合最短路+二进制划分

    题目大意:

    给定一个有向图和一个顶点的集合,求这些顶点两两构成的最短路的最小值。

    思路:

    考虑把这个集合给随机划分,最后的答案s->t有很大概率被划分到了两个不同的集合。
    正解为二进制划分。
    何谓二进制划分?即对于集合中的物品编号,之后枚举其二进制下的每一位,对于每一位,都作一次划分:这一位为1的放入一个集合,这一位为0的放入一个集合。
    考虑这样的正确性,两个不同的物品的编号二进制下必有一位不同,所有任意两个物品一定被划分到了两个不同的集合至少一次。
    二进制划分之后直接跑Djkstra即可。

    #include<bits/stdc++.h>
    
    #define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
    #define pii pair<ll,int>
    #define fi first
    #define se second
    #define mk make_pair
    #define pb push_back
    typedef long long ll;
    
    using namespace std;
    
    void File(){
    	freopen("hdu6166.in","r",stdin);
    	freopen("hdu6166.out","w",stdout);
    }
    
    template<typename T>void read(T &_){
    	T __=0,mul=1; char ch=getchar();
    	while(!isdigit(ch)){
    		if(ch=='-')mul=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
    	_=__*mul;
    }
    
    const int maxn=1e5+10;
    const ll inf=1e18;
    int T,n,m,qu[maxn];
    vector<pii>G[maxn];
    ll dis[maxn],ans;
    
    void init(){
    	read(n); read(m);
    	int u,v; ll w;
    	REP(i,1,m){
    		read(u); read(v); read(w);
    		G[u].pb(mk(w,v));
    	}
    }
    
    priority_queue<pii,vector<pii>,greater<pii> >h;
    void Dijkstra(){
    	while(!h.empty()){
    		int u=h.top().se; ll d=h.top().fi;
    		h.pop();
    		if(d!=dis[u])continue;
    		REP(i,0,G[u].size()-1){
    			int v=G[u][i].se; ll w=G[u][i].fi;
    			if(d+w<dis[v]){
    				dis[v]=d+w;
    				h.push(mk(dis[v],v));
    			}
    		}
    	}
    }
    
    void work(){
    	ans=inf;
    	int sz;
    	read(sz);
    	REP(i,1,sz)read(qu[i]);
    	REP(i,1,17){
    		int base=1<<(i-1);
    		memset(dis,63,sizeof(dis));
    		REP(j,1,sz)if(qu[j]&base)
    			dis[qu[j]]=0,h.push(mk(0,qu[j]));
    		Dijkstra();
    		REP(j,1,sz)if(!(qu[j]&base))
    			ans=min(ans,dis[qu[j]]);
    		memset(dis,63,sizeof(dis));
    		REP(j,1,sz)if(!(qu[j]&base))
    			dis[qu[j]]=0,h.push(mk(0,qu[j]));
    		Dijkstra();
    		REP(j,1,sz)if(qu[j]&base)
    			ans=min(ans,dis[qu[j]]);
    	}
    }
    
    int main(){
    	File();
    	read(T);
    	REP(ca,1,T){
    		init();
    		work();
    		printf("Case #%d: %lld
    ",ca,ans);
    		REP(i,1,n)G[i].clear();
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    (转)当你输入一个网址,实际会发生什么?
    Word Ladder II
    Jump Game II
    Candy
    [生成树][Uva1395][Slim Span]
    [AC自动机][HDU3065]
    [KMP求最小循环节][HDU3746][Cyclic Nacklace]
    [扩展KMP][HDU3613][Best Reward]
    [Manacher][HDU3613][Best Reward]
    [KMP][HDU3336][Count the string]
  • 原文地址:https://www.cnblogs.com/ylsoi/p/9867596.html
Copyright © 2011-2022 走看看