• HDU 6166 二进制分组


    题意 :有向图,点集内的任意两点最短路径的最短值

    思路 :很有意思的题目,直接两两枚举肯定不可以,这里考虑二进制分组,这样只需要分18次就能使得一次分组时最优解在两个不同的集合里面。

    接下来就是分组后缩点一下跑他20次最短路。。很有意思!!

    PS vector被卡了常数。。。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define X first
    #define Y second
    #define PB push_back
    #define MP make_pair
    #define MEM(x,y) memset(x,y,sizeof(x));
    #define bug(x) cout<<"bug"<<x<<endl;
    typedef long long ll;
    typedef pair<int,int> pii;
    using namespace std;
    const ll INF=1e18;
    const int MAXN=200100;
    struct qnode{
        int v,c;
        qnode(int _v=0,int _c=0):v(_v),c(_c) {}
        bool operator <(const qnode &r)const{
            return c>r.c;
        }
    };
    struct Edge{
        int to,next,val;
    }edge[MAXN];
    int head[MAXN],tot;
    bool vis[MAXN];
    ll dist[MAXN];
    void init(){
        tot = 0;memset(head,-1,sizeof(head));
    }
    
    void Dijkstra(int n,int start){
        memset(vis,false,sizeof(vis));
        for(int i=1; i<=n; i++)dist[i]=INF;
        priority_queue<qnode>que;
        while(!que.empty())que.pop();
        dist[start]=0;
        que.push(qnode(start,0));
        qnode tmp;
        while(!que.empty()){
            tmp=que.top();
            que.pop();
            int u=tmp.v;
            if(vis[u])continue;
            vis[u]=true;
            for(int i = head[u];i != -1;i = edge[i].next){
                int v = edge[i].to;
                int cost=edge[i].val;
                if(!vis[v]&&dist[v]>dist[u]+cost){
                    dist[v]=dist[u]+cost;
                    que.push(qnode(v,dist[v]));
                }
            }
        }
    }
    void addedge(int u,int v,int w){
        edge[tot].to = v;
        edge[tot].val = w;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    
    bool st[MAXN];
    int X[MAXN],Y[MAXN],Z[MAXN];
    int main(){
        int t,n,m,k,u,v,x,w;
        scanf("%d",&t);
        for(int ca=1;ca<=t;ca++){
            ll ans=INF;
            MEM(st,0);
            scanf("%d%d",&n,&m);
            for(int i=1;i<=m;i++)scanf("%d%d%d",&X[i],&Y[i],&Z[i]);
            scanf("%d",&k);
            for(int i=0;i<k;i++) scanf("%d",&x),st[x]=1;
            for(int ii=0;ii<=17;++ii){
                int i=r[ii];
                init();
                for(int j=1;j<=m;++j){
                    u=X[j];v=Y[j];w=Z[j];
                    int two=1<<i;
                    if(st[u]&&(u&two)) u=n+1;
                    else if(st[u]&&!(u&two)) u=n+2;
                    if(st[v]&&(v&two)) v=n+1;
                    else if(st[v]&&!(v&two)) v=n+2;
                    if(u!=v)addedge(u,v,w);
                }
                Dijkstra(n+2,n+1);
                ans=min(ans,dist[n+2]);
                Dijkstra(n+2,n+2);
                ans=min(ans,dist[n+1]);
            }
            printf("Case #%d: %lld
    ",ca,ans);
        }
    }
    



  • 相关阅读:
    Http与WWW服务精解
    Http与WWW服务精解
    6-13
    好用的工具说明
    JVM、JRE和JDK三者间的区别和联系
    css进阶之二:flex弹性布局
    MVVM
    如何理解TCP的三次握手协议?
    java里面的设计模式
    linux常用命令
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/10672484.html
Copyright © 2020-2023  润新知