HDU 6166 二进制分组

版权声明:本文为博主原创文章,转载标明出处。 https://blog.csdn.net/xlzhang223/article/details/77984893

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

思路 :很有意思的题目,直接两两枚举肯定不可以,这里考虑二进制分组,这样只需要分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\n",ca,ans);
    }
}



猜你喜欢

转载自blog.csdn.net/xlzhang223/article/details/77984893
今日推荐