ACM-ICPC Live Archive 3645 Objective: Berlin(没通过)

网络流

UVA 1161 是相同的题目

这题网上找不到任何题解的,看上去是个最大流,但是最难搞的就是有时间限制,现在基本上能确定的就是要拆点,但是怎么拆不确定,我用了这种拆法就一直超时

超时的原因我总结一下有几个可能。1.构图的代码太烂,可能出了什么差错但是找不出来。2.数组开小了?开大了?3.和第1个原因,然后运行EK的时候掉进了死循环或者效率太慢。4.EK太慢,要用ISAP

 

超时的代码

/*

原本的点从0到n-1标号,但是每个点需要占用2880个空间,所以对于原来第u个顶点,怎么确定那个范围是它可以用的

就是[u*2880 , (u+1)*2880-1]

如果读入了点u,时间为t而且它是作为到达时间,那么实际对应的点为u*2880+t

如果读入了点u,时间为t而且它是作为出发时间,那么实际上对应的点为u*2880+1440+t

主要在时间转化上可能比较麻烦而且容易出错

*/

#include <cstdio>

#include <cstring>

#include <queue>

#include <algorithm>

using namespace std;

#define MAX 432000 //150*24*60*2=432000

#define L 2880 //每个点需要占用的空间

#define N 160

#define M 5010

#define INF 0x3f3f3f3f

#define min(a,b) a<b?a:b



char city[N][20];

int at[N][L],dt[N][L];

int first[10100]; //最多10000个点

int used[MAX+10];

int ne,nc,nv,n;

int source,target;

int LAST;

struct edge{

    int u,v,cap,flow,next;

}e[10000010];



void add(int u ,int v ,int cap)

{

    e[ne].u=u; e[ne].v=v; e[ne].cap=cap; e[ne].flow=0;

    e[ne].next=first[u]; first[u]=ne++;

    u=u^v; v=u^v; u=u^v;

    e[ne].u=u; e[ne].v=v; e[ne].cap=0; e[ne].flow=0;

    e[ne].next=first[u]; first[u]=ne++;

}



int search_city(char *s)

{

    for(int i=0; i<nc; i++)

        if(!strcmp(s,city[i]))

            return i;

    strcpy(city[nc++],s);

    return nc-1;

}



void input()

{

    char time[10],name[2][10];

    int hour,min,hh,mm,m;

    memset(used,-1,sizeof(used));

    memset(first,-1,sizeof(first));

    for(int i=0; i<n; i++) at[i][0]=dt[i][0]=0;

    scanf("%s%s",city[0],city[1]);

    scanf("%s",time);

    hour=(time[0]-'0')*10+(time[1]-'0');

    min=(time[2]-'0')*10+(time[3]-'0');

    LAST=hour*60+min; //按照分钟来保存时间



   /*

    struct vertex

    {

        int time,n;

    }vt[10100];

    */

    nc=2; ne=0; nv=0;

    scanf("%d",&m);

    while(m--)

    {

        int u,v,cap;

        int index,_index;

        scanf("%s%s%d",name[0],name[1],&cap);

        index=search_city(name[0]);

        _index=search_city(name[1]);



        scanf("%s",time);

        hour=(time[0]-'0')*10+(time[1]-'0');

        min=(time[2]-'0')*10+(time[3]-'0');

        u=index*2880+1440+hour*60+min; //出发点,加1440



        scanf("%s",time);

        hour=(time[0]-'0')*10+(time[1]-'0');

        min=(time[2]-'0')*10+(time[3]-'0');

        v=_index*2880+hour*60+min; //到达点,不加1440



        if(hour*60+min > LAST) continue; //直接抛弃的边



        if(used[u]==-1)

        {

            int t=++dt[index][0]; //出发的点;

            dt[index][t]=u; //出发的点

            used[u]=++nv; //之前没有这个点

//            vt[nv].time=u;

//            vt[nv].n=index;

        }

        if(used[v]==-1)

        {

            int t=++at[_index][0];

            at[_index][t]=v; //到达的点

            used[v]=++nv; //之前没有这个点

//            vt[nv].time=v;

//            vt[nv].n=_index;

        }

        //相当于一个映射,离散化,最后的点标号就是[0,nv-1]



        add(used[u] , used[v] , cap); //用离散化后的点建图

    }

    n=nc;

    for(int i=0; i<n; i++)

        for(int j=1; j<=at[i][0];j++)

            for(int k=1; k<=dt[i][0]; k++)

                if( at[i][j]+30 <= dt[i][k])

                    add(used[at[i][j]] , used[dt[i][k]] , INF);

    source=0; target=++nv;

    for(int i=1; i<=dt[0][0];i++)

        add(source, used[dt[0][i]], INF);

    for(int i=1; i<=at[1][0]; i++)

        add(used[at[1][i]], target, INF);

/*

    for(int i=1; i<=nv-1; i++)

        printf("%d: %d %d\n",i,vt[i].n,vt[i].time);



    for(int i=0; i<ne; i+=2)

    {

        printf("正边: %d %d cap=%d flow=%d\n",e[i].u,e[i].v,e[i].cap,e[i].flow);

        printf("反边: %d %d cap=%d flow=%d\n",e[i+1].u,e[i+1].v,e[i+1].cap,e[i+1].flow);

        printf("\n");

    }



    for(int i=0; i<n; i++)

    {

        printf("%s:\n",city[i]);

        printf("到达时间: ");

        for(int j=1; j<=at[i][0]; j++) printf("%d ",at[i][j]); printf("\n");

        printf("对应顶点: ");

        for(int j=1; j<=at[i][0]; j++) printf("%d ",used[ at[i][j] ]); printf("\n");

        printf("出发时间: ");

        for(int j=1; j<=at[i][0]; j++) printf("%d ",dt[i][j]); printf("\n");

        printf("对应顶点: ");

        for(int j=1; j<=at[i][0]; j++) printf("%d ",used[ dt[i][j] ]); printf("\n");

    }

*/

}



void EK()

{

    int FLOW=0;

    int s=source , t=target;

    while(1)

    {

        queue<int>q;

        int a[10100],p[10100];

        memset(a,0,sizeof(a)); a[s]=INF;

        memset(p,-1,sizeof(p));

        while(!q.empty()) q.pop();

        q.push(s);

        while(!q.empty())

        {

            int u,v,cap,flow;

            u=q.front(); q.pop();

            for(int k=first[u]; k!=-1; k=e[k].next)

            {

                v=e[k].v; cap=e[k].cap; flow=e[k].flow;

                if(!a[v] && cap>flow)

                {

                    a[v]=min(a[u],cap-flow);

                    p[v]=k;

                    q.push(v);

                }

            }

        }

        if(!a[t]) break;

        //printf("_____%d_____\n",a[t]);

        for(int k=p[t]; k!=-1; k=p[e[k].u])

        {

            e[k].flow += a[t];

            e[k^1].flow -= a[t];

        }

        FLOW += a[t];

    }

    //printf("MAX_FLOW=%d\n",FLOW);

    printf("%d\n",FLOW);

}





int main()

{

    while(scanf("%d",&n)!=EOF)

    {

        input();

        EK();

    }

    return 0;

}

 

你可能感兴趣的:(objective)