hdu 3991(最小路径覆盖)

Harry Potter and the Present II

Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 195    Accepted Submission(s): 45


Problem Description
Harry and his friends buy a lot of presents now, but they immediately find they had bought too many presents, so they decide to distribute them to the magicians who need them.
To simplify the problem, here we assume the magic world has N cities and M roads, and there are Q requests, at time Ti, someone at city Pi need a present. After planning the route for a while, Harry realizes he can’t do it by himself, he need to find some friends to help him. But the new question is, how many friends Harry should ask at least? We can assume every magician can choose the original city and time to begin his/her journey, and all of them have the same speed, one unit distance per unit time. And if he/she is exactly in city Pi at time Ti, he/she will give the present in a wink, yes, as you see, they are magicians.
 

Input
The first line contains a single integer T, indicating the number of test cases.
Each test case begins with three integers N, M, Q. Then M lines following, each line contains three integers Ai, Bi, Ci, describing an undirected road. Then Q lines following, each line contains two integers Pi, Ti, describing a request.

Technical Specification

1. 1 <= T <= 50
2. 1 <= N <= 100
3. 1 <= M, Q <= 1 000
4. 0 <= Ai, Bi, Pi < N, Ai != Bi
5. 0 <= Ci, Ti <= 1 000 000 000
 

Output
For each test case, output the case number first, then the least friend number.
 

Sample Input
  
  
2 2 1 2 0 1 1 0 1 1 2 2 1 2 0 1 2 0 1 1 2
 

Sample Output
  
  
Case 1: 0 Case 2: 1
Hint
If you can’t figure out the sample, think twice whether you have forgotten someone named Harry Potter.
 

Author
iSea@WHU
 

Source
 

Recommend
lcy
 
PS:这题被坑惨了。。。比赛时很快就发现是最短路径覆盖,却一直因为不明原因wa。。。原来把点到它本身赋值为无穷了,必须赋为零。。。
分析:这题题意看完也是很明显的,先floyd求出所有点之间的距离,之后直接把需求分点就行,之后随便搞吧,记得点到自身的距离赋为0就行
代码:
#include<cstdio>
#include<algorithm>
using namespace std;
const int mm=1111111;
const int mn=11111;
const int oo=1000000000;
int node,src,dest,edge,ret;
int ver[mm],flow[mm],next[mm];
int head[mn],work[mn],dis[mn],q[mn];
double d[111][111];
struct data
{
    int p;
    double t;
}Q[11111];
inline bool cmp(data a,data b)
{
    return a.t<b.t;
}
inline int min(int a,int b)
{
    return a<b?a:b;
}
inline void prepare(int _node,int _src,int _dest)
{
    node=_node,src=_src,dest=_dest;
    for(int i=0; i<node; ++i)head[i]=-1;
    edge=0;
}
inline void addedge(int u,int v,int c)
{
    ver[edge]=v,flow[edge]=c,next[edge]=head[u],head[u]=edge++;
    ver[edge]=u,flow[edge]=0,next[edge]=head[v],head[v]=edge++;
}
bool Dinic_bfs()
{
    int i,u,v,l,r=0;
    for(i=0; i<node; ++i)dis[i]=-1;
    dis[q[r++]=src]=0;
    for(l=0; l<r; ++l)
        for(i=head[u=q[l]]; i>=0; i=next[i])
            if(flow[i]&&dis[v=ver[i]]<0)
            {
                dis[q[r++]=v]=dis[u]+1;
                if(v==dest)return 1;
            }
    return 0;
}
int Dinic_dfs(int u,int exp)
{
    if(u==dest)return exp;
    for(int &i=work[u],v,tmp; i>=0; i=next[i])
        if(flow[i]&&dis[v=ver[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0)
        {
            flow[i]-=tmp;
            flow[i^1]+=tmp;
            return tmp;
        }
    return 0;
}
int Dinic_flow()
{
    int i,ret=0,delta;
    while(Dinic_bfs())
    {
        for(i=0; i<node; ++i)work[i]=head[i];
        while(delta=Dinic_dfs(src,oo))ret+=delta;
    }
    return ret;
}
int main()
{
    int i,j,k,u,v,n,m,q,c,t,cas=0,ans;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&m,&q);
        for(i=0;i<n;d[i][i]=0,++i)
            for(j=0;j<n;++j)d[i][j]=1e20;
        while(m--)
        {
            scanf("%d%d%d",&u,&v,&c);
            if(c<d[u][v])d[v][u]=d[u][v]=c;
        }
        for(i=0;i<q;++i)
            scanf("%d%lf",&Q[i].p,&Q[i].t);
        for(k=0;k<n;++k)
            for(i=0;i<n;++i)
                if(k!=j)for(j=0;j<n;++j)
                    if(i!=j&&i!=k&&d[i][k]+d[k][j]<d[i][j])d[i][j]=d[i][k]+d[k][j];
        sort(Q,Q+q,cmp);
        prepare(q+q+2,q+q,q+q+1);
        for(i=0;i<q;++i)addedge(src,i,1),addedge(i+q,dest,1);
        for(i=0;i<q;++i)
            for(j=i+1;j<q;++j)
                if(Q[i].t+d[Q[i].p][Q[j].p]-Q[j].t<1e-8)addedge(i,q+j,1);
        ans=q-Dinic_flow();
        if(ans)--ans;
        printf("Case %d: %d\n",++cas,ans);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值