[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

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更优,但我们却不能那样做,因

为那会导致超能电驴爆炸。N≤800,M≤15000。输入数据中的任何数都不会超过106。输入数据保证任意两颗行星

之间至多存在一条航道,且不会存在某颗行星到自己的航道。

Source

第一轮Day2

把每个行星拆点,入点和出点。

S点向每个入点连边,流量1,费用0

S点向每个出点连边,流量1,费用A[i]

每个出点向T点连边,流量1,费用0

对于图上的边,引力小的入点向引力大的出点连边,流量1,费用为边权。

正确性的证明:终于有一个会的了。。。但也只会感性证明

对于一个点的出点来说,如果它的流入的点是S点,说明是从某处瞬移来的。

如果它的流入点是某个点的入点,说明是从那个点飞过来的。

由于每个出点只有1的流量流向T,所以只会有1条入边。

所以这是对的。。。

 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
",mincost());
56     return 0;
57 }
View Code 
原文地址:https://www.cnblogs.com/xzz_233/p/7253460.html