当前位置: 代码迷 >> 综合 >> bzoj 1927
  详细解决方案

bzoj 1927

热度:14   发布时间:2023-10-29 14:13:40.0

1927: [Sdoi2010]星际竞速

Time Limit: 20 Sec   Memory Limit: 259 MB
Submit: 2048   Solved: 1260
[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



一开始想自己做,然而发现并不会。。还是再看多几题,再继续挑战自己构图。。

这题构图很简单,将每一个星球拆成x,y。
然后st连一条边到x,费用为0,流量为1
然后x连一条边到ed,费用为0,流量为1
假如有一条合法的跑道a——>b,则连一条x_a——>y_b,费用为这条跑道的值,流量还是1
接着就是最重要的一步st——>y,流量为1,费用为a[y]
因为假如你想使用跳转,值是一定的,所以一开始连就行了

像网络流这种东西,还是知道构图之后,只可意会不可言传~

蒟蒻代码:
#include<cstdio>
#include<cstring>
const int N=2000;
const int M=150000;
struct qq
{int x,y,z,z1;int last,other;
}s[M];
int num,last[N];
int init1 (int x,int y,int z,int z1)
{num++;s[num].x=x;s[num].y=y;s[num].z=z;s[num].z1=z1;s[num].last=last[x];last[x]=num;return num;
}
void init (int x,int y,int z,int z1)
{int num1=init1(x,y,z,z1),num2=init1(y,x,0,-z1);s[num1].other=num2;s[num2].other=num1;return ;
}
int n,m;//顾客数  技术人员
int st1,ed1;
int ans=0;
int from[N],f[N],q[N];
bool ooo[N];
bool bt ()
{memset(ooo,false,sizeof(ooo));memset(f,127,sizeof(f));memset(from,-1,sizeof(from));int st=1,ed=2;q[st]=st1;f[st1]=0;ooo[st1]=true;while (st!=ed){int x=q[st];for (int u=last[x];u!=-1;u=s[u].last){int y=s[u].y;if (s[u].z>0&&f[y]>f[x]+s[u].z1){f[y]=f[x]+s[u].z1;from[y]=u;if (ooo[y]==false){ooo[y]=true;q[ed]=y;ed++;if (ed>=N-1) ed=1;}}}ooo[x]=false;st++;if (st>=N-1) st=1;}if (from[ed1]==-1) return false;return true;
}
int mymin (int x,int y)
{return x<y?x:y;
}
void add ()
{int x=ed1,f=10000000;while (from[x]!=-1){f=mymin(f,s[from[x]].z);x=s[from[x]].x;}x=ed1;while (from[x]!=-1){ans=ans+f*s[from[x]].z1;s[from[x]].z-=f;s[s[from[x]].other].z+=f;x=s[from[x]].x;}return ;
}
int main()
{num=0;memset(last,-1,sizeof(last));int n,m;scanf("%d%d",&n,&m);st1=n*2+1;ed1=st1+1;for (int u=1;u<=n;u++){int a;scanf("%d",&a);init(st1,u+n,1,a);init(st1,u,1,0);init(u+n,ed1,1,0);}for (int u=1;u<=m;u++){int x,y,z;scanf("%d%d%d",&x,&y,&z);if (x>y) {int tt=x;x=y;y=tt;}init(x,y+n,1,z);}while (bt()==true)	add();printf("%d\n",ans);return 0;
}