首页 > 代码库 > Shopping(hdu 3768)

Shopping(hdu 3768)

题意:给你一个无向图,求从0号点开始遍历所有的指定点再回到0号点的最短路径

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#define N 100010
#define ll long long
#define INF 10000000000000LL
using namespace std;
ll head[N],vis[N],dis[N],f[15][15],a[15],b[15],n,m,k,ans=INF;
struct node
{
    ll v,pre,t;
};node e[N*2];
ll read()
{
    ll num=0,flag=1;char c=getchar();
    while(c<0||c>9){if(c==-)flag=-1;c=getchar();}
    while(c>=0&&c<=9){num=num*10+c-0;c=getchar();}
    return num*flag;
}
void add(ll i,ll x,ll y,ll z)
{
    e[i].v=y;
    e[i].t=z;
    e[i].pre=head[x];
    head[x]=i;
}
ll spfa(ll s,ll t)
{
    for(ll i=1;i<=n;i++)dis[i]=INF;
    memset(vis,0,sizeof(vis));
    queue<int> q;
    q.push(s);vis[s]=1;dis[s]=0;
    while(!q.empty())
    {
        ll u=q.front();vis[u]=0;q.pop();
        for(ll i=head[u];i;i=e[i].pre)
          if(dis[e[i].v]>dis[u]+e[i].t)
          {
              dis[e[i].v]=dis[u]+e[i].t;
              if(!vis[e[i].v])
              {
                  vis[e[i].v]=1;
                  q.push(e[i].v);
              }
          }
    }
    return dis[t];
}
void work()
{
    n=read();m=read();
    for(ll i=1;i<=m;i++)
    {
        ll x=read()+1,y=read()+1,z=read();
        add(i*2-1,x,y,z);add(i*2,y,x,z);
    }
    k=read();a[1]=1;
    for(ll i=2;i<=k+1;i++)
      a[i]=read()+1;
    for(ll i=1;i<=k+1;i++)
      for(ll j=i+1;j<=k+1;j++)
        f[i][j]=f[j][i]=spfa(a[i],a[j]);
    for(ll i=1;i<=k+1;i++)b[i]=i;
    do
    {
        ll p=f[b[1]][b[k+1]];
        for(ll i=2;i<=k+1;i++)
          p+=f[b[i-1]][b[i]];
        ans=min(ans,p);
    }while(next_permutation(b+2,b+k+2));
    cout<<ans<<endl;
}
int main()
{
    freopen("jh.in","r",stdin);
    ll T=read();
    while(T--)
    {
        memset(head,0,sizeof(head));
        memset(f,0,sizeof(f));
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(e,0,sizeof(e));
        ans=INF;
        work();
    }
    return 0;
}

 

Shopping(hdu 3768)