hdu5521 Meeting

本文介绍了一种解决农场中两个角色Bessie与Elsie如何快速会面的问题的算法。通过建立特殊的网络流模型,并采用SPFA算法找到最短路径,进而确定它们会面所需的最短时间和地点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem Description Bessie and her friend Elsie decide to have a
meeting. However, after Farmer John decorated his fences they were
separated into different blocks. John’s farm are divided into n blocks
labelled from 1 to n. Bessie lives in the first block while Elsie
lives in the n-th one. They have a map of the farm which shows that it
takes they ti minutes to travel from a block in Ei to another block in
Ei where Ei (1≤i≤m) is a set of blocks. They want to know how soon
they can meet each other and which block should be chosen to have the
meeting.

Input The first line contains an integer T (1≤T≤6), the number of test
cases. Then T test cases follow.

The first line of input contains n and m. 2≤n≤105. The following m
lines describe the sets Ei (1≤i≤m). Each line will contain two
integers ti(1≤ti≤109) and Si (Si>0) firstly. Then Si integer follows
which are the labels of blocks in Ei. It is guaranteed that
∑mi=1Si≤106.

Output For each test case, if they cannot have the meeting, then
output “Evil John” (without quotes) in one line.

Otherwise, output two lines. The first line contains an integer, the
time it takes for they to meet. The second line contains the numbers
of blocks where they meet. If there are multiple optional blocks,
output all of them in ascending order.

如果把每一块里的点彼此之间连边,那么肯定存不下。
可以借鉴网络流的建图思想,考虑如何增加一些节点来让问题易于表示。
可以对于每一块新建一个入点一个出点,入点向每个点连一条0的边,每个点向出点连一条0的边,出点向入点连一条边权为这一块里移动费用的边。
这样再用spfa求最短路即可。
另外注意审清题目要求,可以参照样例解释。

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define M(a) memset(a,0,sizeof(a))
using namespace std;
int fir[5000010],ne[5000010],to[5000010],len[5000010],dis1[5000010],disn[5000010],m,n,tot;
bool is[5000010];
queue<int> q;
vector<int> v;
int max(int x,int y)
{
    return x>y?x:y;
}
void add(int f,int t,int l)
{
    tot++;
    ne[tot]=fir[f];
    fir[f]=tot;
    to[tot]=t;
    len[tot]=l;
}
void in()
{
    M(fir);
    M(ne);
    tot=0;
    int i,j,k,x,y,z;
    scanf("%d%d",&n,&m);
    for (i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        add(n+i*2,n+i*2+1,x);
        for (j=1;j<=y;j++)
        {
            scanf("%d",&z);
            add(z,n+i*2,0);
            add(n+i*2+1,z,0);
        }
    }
}
void spfa()
{
    int i,j,k,p,x,y,z;
    memset(dis1,0x3f,sizeof(dis1));
    dis1[1]=0;
    while (!q.empty()) q.pop();
    q.push(1);
    while (!q.empty())
    {
        x=q.front();
        q.pop();
        for (i=fir[x];i;i=ne[i])
          if (dis1[x]+len[i]<dis1[to[i]])
          {
            dis1[to[i]]=dis1[x]+len[i];
            q.push(to[i]);
          }
    }
    memset(disn,0x3f,sizeof(disn));
    disn[n]=0;
    q.push(n);
    while (!q.empty())
    {
        x=q.front();
        q.pop();
        for (i=fir[x];i;i=ne[i])
          if (disn[x]+len[i]<disn[to[i]])
          {
            disn[to[i]]=disn[x]+len[i];
            q.push(to[i]);
          }
    }
}
void out()
{
    int i,j,k,ans=0x3f3f3f3f;
    v.clear();
    for (i=1;i<=n;i++)
      if (max(dis1[i],disn[i])<ans)
      {
        v.clear();
        v.push_back(i);
        ans=max(dis1[i],disn[i]);
      }
      else if (max(dis1[i],disn[i])==ans) v.push_back(i);
    if (ans==0x3f3f3f3f)
      printf("Evil John\n");
    else
    {
        printf("%d\n",ans);
        for (i=0;i<v.size();i++)
          printf("%d%c",v[i],i==v.size()-1?'\n':' ');
    }
}
int main()
{
    int T,K;
    scanf("%d",&T);
    for (K=1;K<=T;K++)
    {
        printf("Case #%d: ",K);
        in();
        spfa();
        out();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值