Gym - 101196D -BFS+优先队列

你是一个翻译官,翻啊翻译官。
给定n,n个目标语言,
求你把英语翻译成其他语种的最小花费,
并且要求距离英语最近。。(经过一个第三方翻译,就是两层),直接翻译就是一层。

由于第二个条件的限制,所以不是最短路啦。
但是在比赛的时候,我觉得可以先用dinic跑一下层数,然后再跑一下spfa,在判断是否为松弛操作的时候,加一个限制条件,那就是层数必须小。
但是很可悲的wa了。应该是有数据卡。
第九组数据过不了
因为这样写本来就得到的是有限制条件的最短路,但是并不能证明最终要输出的路径是一个最短路,
附上错误代码,原谅我这个逗逼–

wa的代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int maxn=6000;
struct Node
{  char a[maxn];
   int num;

}node[maxn*2];
struct Tree
{ int from,to,cost,next;

}tree[maxn*2];
int n,m;
int head[maxn];
int len;
bool vis[maxn];
int dis[maxn];
int ranks[maxn];
int pre[maxn];
int check(char x[])
{  for(int i=0;i<=n;i++)
    {  if(strcmp(node[i].a,x)==0)
        {
             //printf("%s  %s\n",node[i].a,x);
             return i;
        }
       //return i;
    }
    return -1;
}
void add(int u,int v,int value)
{   tree[len].from=u;
    tree[len].to=v;
    tree[len].cost=value;
    tree[len].next=head[u];
    head[u]=len++;

}
void init()
{  memset(head,-1,sizeof(head));
   len=0;
}
void spfa()
{
      memset(dis,0x3f,sizeof(dis));
   memset(pre,-1,sizeof(pre));
    memset(vis,0,sizeof(vis));
    dis[0]=0;
    vis[0]=true;
    queue<int>q;
    q.push(0);

    while(!q.empty())
    {   int u=q.front();
         q.pop();
         vis[u]=false;
        for(int i=head[u];i!=-1;i=tree[i].next)
         {   int s=tree[i].to;
             int len=tree[i].cost;
             if(dis[s]>dis[u]+len&&ranks[s]>=ranks[u]+1)//there
             {  dis[s]=len+dis[u];
                pre[s]=u;
                       if(!vis[s])
                        {q.push(s);
                         vis[s]=1;}

             }


             }

        }

   // for(int i=1;i<=m;i++)
         //cout<<dis[i]<<endl;
    return ;


}
int ceshi()
{   for(int i=0;i<=n;i++)
     if(dis[i]==0x3f3f3f3f)
        return -1;
    int sum=0;
    /*for(int i=0;i<=n;i++)
   for(int j=head[i];j!=-1;j=tree[j].next)
   {  if(dis[i]+tree[j].cost==dis[tree[j].to])
        { //printf("%d  %d  %d\n",i,tree[j].to,tree[j].cost);
            sum+=tree[j].cost;}*/

   /*for(int i=1;i<=n;i++)
      sum+=dis[i];*/

      for(int i=1;i<=n;i++)
      {  if(pre[i]!=-1)
        {   int s=pre[i];
            for(int j=head[s];j!=-1;j=tree[j].next)
            {  int l=tree[j].to;
                if(l==i)
                    {sum+=tree[j].cost;
                    break;
                    }

            }

        }


      }
    return sum;
}
void bfs()
{
     queue<int>q;
   memset(ranks,-1,sizeof(ranks));
    ranks[0]=1;
    q.push(0);
    while(!q.empty())
    {   int u=q.front();
        q.pop();
        for(int i=head[u];i!=-1;i=tree[i].next)
        {   int e=tree[i].to;
           if(ranks[e]==-1)
           {  ranks[e]=ranks[u]+1;
              q.push(e);
           }
        }
    }
    return ;

}
int main()
{
    while(scanf("%d%d",&n,&m)!=-1)
      {



    char x[maxn];
     char y[maxn];
     strcpy(node[0].a,"English");
      node[0].num=0;
     //getchar();
     //printf("%s************\n",node[0].a);
    for(int i=1;i<=n;i++)
    {    cin>>x;
         strcpy(node[i].a,x);
           node[i].num=i;
    }
    //printf("%s\n",node[1].a);
    init();
    int num=0;
    for(int i=1;i<=m;i++)
    {    cin>>x>>y>>num;
       //printf("%s %s\n",x,y);
         int x1=check(x);
         //printf("****%d\n",x1);
        int y1=check(y);
        //printf("%d %d\n",x1,y1);
         add(x1,y1,num);
         add(y1,x1,num);

    }
    /*for(int i=0;i<=n;i++)
        for(int j=head[i];j!=-1;j=tree[j].next)
    {   printf("%d %d %d\n",i,tree[j].to,tree[j].cost);

    }*/
  bfs();
   //for(int i=0;i<=n;i++)
    //printf("%d  \n",ranks[i]);
    spfa();
    int l=ceshi();
    if(l!=-1)
    printf("%d\n",l);
    else
        printf("Impossible\n");
    return 0;}
}

2 正确的打开方式
用优先队列轻松搞定。妈蛋就是一个stl的题。。
我算是明白了。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <map>
#include <string>
#include <cstring>
const int maxn=2000;
using namespace std;
struct Node
{   int to,c,w;
   Node(int a,int b,int m){to=a;c=b;w=m;}
};//node[maxn];
int len;
bool operator<(const Node &a,const Node &b)
{    if(a.c==b.c)
    return a.w>b.w;
    return a.c>b.c;
}
bool vis[maxn];
priority_queue<Node>que;
vector<Node>G[maxn];
map<string,int>p;
int main()
{  int n,m;
string t,s;
int cost;
   scanf("%d%d",&n,&m);

        p["English"]=0;
        for(int i=1;i<=n;i++)
        {cin>>t;
        p[t]=i;}
      for(int i=1;i<=m;i++)
      {  cin>>t>>s>>cost;
         int x=p[t];
         int y=p[s];
         G[x].push_back(Node(y,0,cost));
         G[y].push_back(Node(x,0,cost));
         //printf("%d   %d\n",x,y);
      }
       memset(vis,false,sizeof(vis));
       que.push(Node(0,0,0));
       //vis[0]=true;
       int sum=0;
       while(!que.empty())
       {  Node u=que.top();
          que.pop();
          //printf("    %d  **\n",u.to);
          if(vis[u.to]) continue;
          //if(!vis[u.to])
          //printf("%d\n",u.w);
            sum+=u.w;
              vis[u.to]=true;

         for(int i=0;i<G[u.to].size();i++)
         {   int s=G[u.to][i].to;
             //int c=G[u.to][i].c;
             int w=G[u.to][i].w;
             que.push(Node(s,u.c+1,w));
         }
         //vis[u.to]=true;
       }

       for(int i=1;i<=n;i++)
       {  if(!vis[i])
          {printf("Impossible\n");
            return 0;}


       }
     printf("%d\n",sum);





    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值