hdu5521 Meeting

来源:互联网 发布:沂南知豆租赁怎么办理 编辑:程序博客网 时间:2024/04/29 07:17

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();    }}
0 0