hdu6166(xjb迪杰斯特拉)

来源:互联网 发布:v盾网络验证破解 编辑:程序博客网 时间:2024/06/06 17:12

类比cf 835E,枚举二进制位按照标号当前位为1 和当前位为0分为两个集合,每次求解两个集合之间的最短路即可覆盖到所有的点对。时间复杂度20*dijstla时间

G++ AC c++会超时。

#include<cstdio>#include<algorithm>#include<queue>#include<cstring>using namespace std;typedef long long ll;const ll inf = 0x3f3f3f3f3f3f3f3fLL;const int maxn = 100010;int n;struct node{    int to;    int next;    ll w;    node(){}    node(int a,int b,ll c):to(a),next(b),w(c){}}edge[maxn<<1];struct Edge{    int id;    ll dist;    Edge(int a, ll b):id(a),dist(b){}    bool operator < (const Edge& T)const{        return dist>T.dist;    }};ll dist[maxn],z[maxn];int tot;int head[maxn];int x[maxn],y[maxn],c[maxn];void add_edge(int u,int v,ll w){    edge[tot] = node(v,head[u],w);    head[u] = tot++;}priority_queue<Edge>q;long long dij(){    for(int i=0;i<=n+1;i++) dist[i]=inf;    dist[0] = 0;    q.push(Edge(0,0));    while(!q.empty())    {        Edge fr = q.top(); q.pop();        int u = fr.id;        if(dist[u]<fr.dist) continue;        for(int i=head[u];i!=-1;i=edge[i].next)        {            int v = edge[i].to;            if(dist[v]>dist[u] + edge[i].w)            {                dist[v] = dist[u] + edge[i].w;                //printf("%lld\n",dist[v]);                q.push(Edge(v,dist[v]));            }        }    }    //printf("%I64d\n",dist[n+1]);    return dist[n+1];}int main(){    int cases,t=1,m,k;    scanf("%d",&cases);    while(cases--)    {        scanf("%d%d",&n,&m);        for(int i=0;i<m;i++)            scanf("%d%d%I64d",&x[i],&y[i],&z[i]);        scanf("%d",&k);        for(int i=0;i<k;i++) scanf("%d",&c[i]);        ll ans = inf;        for(int r=0;r<20;r++)        {            tot = 0; memset(head,-1,sizeof(head));            for(int i=0;i<m;i++) add_edge(x[i],y[i],z[i]);            for(int i=0;i<k;i++)            {                if(c[i]&(1<<r)) add_edge(0,c[i],0);                else add_edge(c[i],n+1,0);            }            ans = min(ans,dij());            tot = 0; memset(head,-1,sizeof(head));            for(int i=0;i<m;i++) add_edge(x[i],y[i],z[i]);            for(int i=0;i<k;i++)            {                if((c[i]&(1<<r))==0) add_edge(0,c[i],0);                else add_edge(c[i],n+1,0);            }            ans = min(ans,dij());        }        printf("Case #%d: ",t++);        printf("%I64d\n",ans);    }    return 0;}