[bzoj1927][SDOI2010]星际竞速
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
1 100 100
2 1 10
1 3 1
2 3 1
Sample Output
HINT
说明:先使用能力爆发模式到行星1,花费时间1。然后切换到高速航行模式,航行到行星2,花费时间10。之
后继续航行到行星3完成比赛,花费时间1。虽然看起来从行星1到行星3再到行星2更优,但我们却不能那样做,因
为那会导致超能电驴爆炸。N≤800,M≤15000。输入数据中的任何数都不会超过106。输入数据保证任意两颗行星
之间至多存在一条航道,且不会存在某颗行星到自己的航道。
Source
把每个行星拆点,入点和出点。
S点向每个入点连边,流量1,费用0
S点向每个出点连边,流量1,费用A[i]
每个出点向T点连边,流量1,费用0
对于图上的边,引力小的入点向引力大的出点连边,流量1,费用为边权。
正确性的证明:终于有一个会的了。。。但也只会感性证明
对于一个点的出点来说,如果它的流入的点是S点,说明是从某处瞬移来的。
如果它的流入点是某个点的入点,说明是从那个点飞过来的。
由于每个出点只有1的流量流向T,所以只会有1条入边。
所以这是对的。。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 // It is made by XZZ 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 #define rep(a,b,c) for(rg int a=b;a<=c;a++) 7 #define drep(a,b,c) for(rg int a=b;a>=c;a--) 8 #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a]) 9 #define il inline 10 #define rg register 11 #define vd void 12 #define t (dis[i]) 13 typedef long long ll; 14 il int gi(){ 15 rg int x=0;rg char ch=getchar(); 16 while(ch<'0'||ch>'9')ch=getchar(); 17 while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); 18 return x; 19 } 20 const int maxN=810,maxM=15010; 21 int A[maxN]; 22 const int maxn=maxN<<1,maxm=(maxM+maxn+maxn+maxn)<<1,S=0,T=1601; 23 int fir[maxn],dis[maxm],w[maxm],nxt[maxm],cost[maxm],id=1; 24 il vd add(int a,int b,int c,int d){ 25 nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c,cost[id]=d; 26 if(c)add(b,a,0,-d); 27 } 28 il bool Super_Fast(int&Cost){ 29 int que[maxn],hd=0,tl=1,Dis[maxn],last[maxn]={0};bool inque[maxn]={0}; 30 memset(Dis,127/3,sizeof Dis);Dis[S]=0; 31 que[0]=S,inque[S]=1; 32 while(hd^tl){ 33 int now=que[hd];hd=(hd+1)%maxn,inque[now]=0; 34 erep(i,now) 35 if(Dis[now]+cost[i]<Dis[t]&&w[i]){ 36 Dis[t]=Dis[now]+cost[i],last[t]=i; 37 if(!inque[t])que[tl++]=t,inque[t]=1,tl%=maxn; 38 } 39 } 40 if(!last[T])return false; 41 rg int flow=666666666; 42 for(rg int i=last[T];i;i=last[dis[i^1]])flow=min(flow,w[i]); 43 for(rg int i=last[T];i;i=last[dis[i^1]])w[i]-=flow,w[i^1]+=flow,Cost+=cost[i]*flow; 44 return true; 45 } 46 il int mincost(int Cost=0){ 47 while(Super_Fast(Cost)); 48 return Cost; 49 } 50 int main(){ 51 int n=gi(),m=gi(),a,b,c; 52 rep(i,1,n)A[i]=gi(); 53 while(m--)a=gi(),b=gi(),c=gi(),add(min(a,b),max(a,b)+n,1,c); 54 rep(i,1,n)add(S,i+n,1,A[i]),add(i+n,T,1,0),add(S,i,1,0); 55 printf("%d\n",mincost()); 56 return 0; 57 }
本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。