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;
}

 

posted @ 2013-04-02 19:54  Titanium  阅读(342)  评论(0编辑  收藏  举报