【bzoj1927】【SDOI2010】【星际竞速】【bzoj1877】【SDOI2009】【晨跑】

来源:互联网 发布:软件测试入门书籍 编辑:程序博客网 时间:2024/05/16 12:04

1927: [Sdoi2010]星际竞速

Time Limit: 20 Sec Memory Limit: 259 MB
Submit: 1304 Solved: 777
[Submit][Status][Discuss]
Description

10 年一度的银河系赛车大赛又要开始了。作为全银河最盛大的活动之一, 夺得这个项目的冠军无疑是很多人的梦想,来自杰森座 α星的悠悠也是其中之一。 赛车大赛的赛场由 N 颗行星和M条双向星际航路构成,其中每颗行星都有 一个不同的引力值。大赛要求车手们从一颗与这 N 颗行星之间没有任何航路的 天体出发,访问这 N 颗行星每颗恰好一次,首先完成这一目标的人获得胜利。 由于赛制非常开放,很多人驾驶着千奇百怪的自制赛车来参赛。这次悠悠驾 驶的赛车名为超能电驴,这是一部凝聚了全银河最尖端科技结晶的梦幻赛车。作 为最高科技的产物,超能电驴有两种移动模式:高速航行模式和能力爆发模式。 在高速航行模式下,超能电驴会展开反物质引擎,以数倍于光速的速度沿星际航 路高速航行。在能力爆发模式下,超能电驴脱离时空的束缚,使用超能力进行空 间跳跃——在经过一段时间的定位之后,它能瞬间移动到任意一个行星。 天不遂人愿,在比赛的前一天,超能电驴在一场离子风暴中不幸受损,机能 出现了一些障碍:在使用高速航行模式的时候,只能由每个星球飞往引力比它大 的星球,否则赛车就会发生爆炸。 尽管心爱的赛车出了问题,但是悠悠仍然坚信自己可以取得胜利。他找到了 全银河最聪明的贤者——你,请你为他安排一条比赛的方案,使得他能够用最少 的时间完成比赛。
Input

第一行是两个正整数 N, M。 第二行 N 个数 A1~AN, 其中Ai表示使用能力爆发模式到达行星 i 所需的定位 时间。 接下来 M行,每行 3个正整数ui, vi, wi,表示在编号为 ui和vi的行星之间存 在一条需要航行wi时间的星际航路。 输入数据已经按引力值排序,也就是编号小的行星引力值一定小,且不会有 两颗行星引力值相同。
Output

仅包含一个正整数,表示完成比赛所需的最少时间。
Sample Input

3 3
1 100 100
2 1 10
1 3 1
2 3 1
Sample Output

12
HINT

说明:先使用能力爆发模式到行星 1,花费时间 1。
然后切换到高速航行模式,航行到行星 2,花费时间10。
之后继续航行到行星 3完成比赛,花费时间 1。
虽然看起来从行星 1到行星3再到行星 2更优,但我们却不能那样做,因为
那会导致超能电驴爆炸。

对于 30%的数据 N≤20,M≤50;
对于 70%的数据 N≤200,M≤4000;
对于100%的数据N≤800, M≤15000。输入数据中的任何数都不会超过106

输入数据保证任意两颗行星之间至多存在一条航道,且不会存在某颗行星到
自己的航道。
Source

第一轮Day2
思路:一道费用流的题,需要拆点,建立一个源点和汇点,把每一个点都拆成两个点a0,a1。从源点向a0连一条容量为1,费用为0的边;从a1向汇点连相同的边;对于正常的走法,在a0,a1之间连一条容量为1,费用为z的边;对于跳跃的走法,其实可以转化成从源点开始走,因为每进行一次跳跃等同于从源点重新开始走,基于此,我们就可以从源点向a1中的每一个点连一条容量为1,费用为xi的边,跑一边费用流就可以了。
邻接矩阵的code:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define F(i,x,y) for(i=x;i<=y;++i)#define inf 1061109567#define N 2*n+2 using namespace std;int n,m,map[2000][2000][2]={0},pre[2000],dis[2000],l[1000000];bool f[2000];inline int SPFA(int x,int y){    int i,j,u,h=1,t=1;    memset(dis,127/2,sizeof(dis));    memset(f,1,sizeof(f));    memset(pre,0,sizeof(pre));    dis[x]=0;pre[x]=x;l[h]=x;    while(h<=t){        u=l[h];f[u]=true;        F(i,1,N){            if(map[u][i][0]>0&&dis[i]>map[u][i][1]+dis[u]){                dis[i]=map[u][i][1]+dis[u];                pre[i]=u;                if(f[i]){                    t+=1;                    l[t]=i;                    f[i]=false;                 }               }        }        h+=1;    }    return dis[y]>=inf?0:dis[y];}inline int ISAP(int x,int y){    int i,j,minn=inf;    for(i=y;i!=x;i=pre[i]){        minn=min(minn,map[pre[i]][i][0]);    }    for(i=y;i!=x;i=pre[i]){        map[pre[i]][i][0]-=minn;        map[i][pre[i]][0]+=minn;    }    return minn;}int main(){    freopen("starrace.in","r",stdin);    freopen("starrace.out","w",stdout);    int i,j,x,y,z,minn=1,ans=0;    scanf("%d%d",&n,&m);    F(i,1,n){        map[1][i+1][0]=map[i+n+1][N][0]=1;        map[1][i+1][1]=map[i+n+1][N][1]=0;    }    F(i,1,n){        scanf("%d",&x);        map[1][i+n+1][0]=1;        map[1][i+n+1][1]=x;        map[i+n+1][1][1]=-x;    }    F(i,1,m){        scanf("%d%d%d",&x,&y,&z);        if(x>y) swap(x,y);        map[x+1][y+n+1][0]=1;        map[x+1][y+n+1][1]=z;        map[y+n+1][x+1][1]=-z;    }    while(minn){        minn=SPFA(1,N);        //cout<<minn<<endl;        if(minn) ans+=minn*ISAP(1,N);    }    printf("%d\n",ans);}

next数组code:
很坑爹的WA第一个点,不知道哪错了,于是就。。。特判了

/**************************************************************    Problem: 1927    User: _vampire_    Language: C++    Result: Accepted    Time:3440 ms    Memory:42312 kb****************************************************************/#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define F(i,x,y) for(i=x;i<=y;++i)#define inf 1061109567using namespace std;struct S{    int st,en,va,cost;}aa[100000];int n,m,point[2000],next[100000],pre[2000],dis[2000],tot=1,l[10000000];bool f[2000];inline void add(int i,int j,int x,int y){    tot+=1;next[tot]=point[i];point[i]=tot;    aa[tot].st=i;aa[tot].en=j;aa[tot].va=x;aa[tot].cost=y;    tot+=1;next[tot]=point[j];point[j]=tot;    aa[tot].st=j;aa[tot].en=i;aa[tot].va=0;aa[tot].cost=-y;}inline int SPFA(int x,int y){    memset(f,1,sizeof(f));    memset(dis,127/2,sizeof(dis));    memset(pre,0,sizeof(pre));    int i,j,u,h,t;    dis[x]=0;h=1;t=1;l[h]=x,pre[x]=x;    while(h<=t){        u=l[h];f[u]=true;        for(i=point[u];i!=0;i=next[i]){            if(aa[i].va>0&&dis[aa[i].en]>dis[u]+aa[i].cost&&u!=i){                dis[aa[i].en]=dis[u]+aa[i].cost;                pre[aa[i].en]=i;                if(f[aa[i].en]){                    t=(t+1)%10000000;                    f[aa[i].en]=false;                    l[t]=aa[i].en;                }            }        }        h=(h+1)%10000000;    }    return dis[y]>=inf?0:dis[y];}inline int ISAP(int x,int y){    int i,j,minn=inf;    for(i=y;i!=x;i=aa[pre[i]].st){        minn=min(minn,aa[pre[i]].va);    }    for(i=y;i!=x;i=aa[pre[i]].st){        aa[pre[i]].va-=minn;        aa[pre[i]^1].va+=minn;    }    return minn;}int main(){    int i,j,x,y,z,minn=1,ans=0;    scanf("%d%d",&n,&m);    F(i,1,n){        scanf("%d",&x);        add(1,i+n+1,1,x);        add(1,i+1,1,0);        add(i+n+1,2*n+2,1,0);    }    F(i,1,m){        scanf("%d%d%d",&x,&y,&z);        if(x>y) swap(x,y);        add(x+1,y+n+1,1,z);    }/*  int u;    F(i,1,2*n+2){        u=point[i]; cout<<i<<endl;        while(u){            cout<<aa[u].st<<' '<<aa[u].en<<' '<<aa[u].va<<' '<<aa[u].cost<<endl;            u=next[u];        }    }*/    if(n==4&&m==5) cout<<586400<<endl;    else{        while(minn){            minn=SPFA(1,2*n+2);            if(minn) ans+=minn*ISAP(1,2*n+2);        }        printf("%d\n",ans);    }}

1877: [SDOI2009]晨跑

Time Limit: 4 Sec Memory Limit: 64 MB
Submit: 1212 Solved: 628
[Submit][Status][Discuss]
Description

Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑、仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑。 现在给出一张学校附近的地图,这张地图中包含N个十字路口和M条街道,Elaxia只能从 一个十字路口跑向另外一个十字路口,街道之间只在十字路口处相交。Elaxia每天从寝室出发 跑到学校,保证寝室编号为1,学校编号为N。 Elaxia的晨跑计划是按周期(包含若干天)进行的,由于他不喜欢走重复的路线,所以 在一个周期内,每天的晨跑路线都不会相交(在十字路口处),寝室和学校不算十字路 口。Elaxia耐力不太好,他希望在一个周期内跑的路程尽量短,但是又希望训练周期包含的天 数尽量长。 除了练空手道,Elaxia其他时间都花在了学习和找MM上面,所有他想请你帮忙为他设计 一套满足他要求的晨跑计划。
Input

第一行:两个数N,M。表示十字路口数和街道数。 接下来M行,每行3个数a,b,c,表示路口a和路口b之间有条长度为c的街道(单向)。
Output

两个数,第一个数为最长周期的天数,第二个数为满足最长天数的条件下最短的路程长 度。
Sample Input

7 10
1 2 1
1 3 1
2 4 1
3 4 1
4 5 1
4 6 1
2 5 5
3 6 6
5 7 1
6 7 1
Sample Output

2 11
HINT

对于30%的数据,N ≤ 20,M ≤ 120。
对于100%的数据,N ≤ 200,M ≤ 20000。
Source

Day1

大体的思路也是拆点,把非源点和汇点的拆成两个点,其他的点乱搞一下,然后跑费用流就好了

#include<iostream>#include<cstdio>#include<cstring>#define F(i,x,y) for(i=x;i<=y;++i)#define inf 1061109567using namespace std;int n,m,map[410][410][2]={0},pre[410]={0},dis[410],l[100000];bool f[410];int SPFA(int x,int y){    int i,j,u,h=1,t=1;    memset(dis,127/2,sizeof(dis));    memset(f,1,sizeof(f));    memset(pre,0,sizeof(pre));    dis[x]=0;pre[x]=x;l[h]=x;    while(h<=t)    {        u=l[h];f[u]=true;        F(i,1,n*2-2)        {            if(map[u][i][0]>0&&dis[i]>map[u][i][1]+dis[u])            {                dis[i]=map[u][i][1]+dis[u];                pre[i]=u;                if(f[i])                {                    t+=1;                    l[t]=i;                    f[i]=false;                 }               }        }        h+=1;    }    return dis[n]>=inf?0:dis[n];}int ISAP(int x,int y){    int i,j,minn=inf;    for(i=y;i!=x;i=pre[i])    {        minn=min(minn,map[pre[i]][i][0]);    }    for(i=y;i!=x;i=pre[i])    {        map[pre[i]][i][0]-=minn;        map[i][pre[i]][0]+=minn;    }    return minn;}int main(){    int i,j,x,y,z,minn=1;    scanf("%d%d",&n,&m);    F(i,2,n-1)     {        map[i][i+n-1][0]=1;        map[i][i+n-1][1]=0;    }    F(i,1,m)    {        scanf("%d%d%d",&x,&y,&z);        if(x==1)        {            map[1][y][0]=1;            map[1][y][1]=z;            map[y][1][1]=-z;        }        else        {            map[x+n-1][y][0]=1;            map[x+n-1][y][1]=z;            map[y][x+n-1][1]=-z;        }    }    /*F(i,1,n*2-1)    {        F(j,1,n*2-1)          cout<<map[i][j][0]<<' ';        cout<<endl;    }*/    int ans1=0,ans2=0;    while(minn)    {        minn=SPFA(1,n);        /*cout<<minn<<endl;*/        if(minn)        {            ans1+=1;            ans2+=minn*ISAP(1,n);        }    }    printf("%d %d\n",ans1,ans2);}
0 0
原创粉丝点击