BZOJ 1927 星际竞速

http://www.lydsy.com/JudgeOnline/problem.php?id=1927

思路:把一个点拆成两个点,

S->i 费用0,流量1 (代表这个点可以移动到其他点所必备的流量)

i+n->T 费用0,流量1 (每个点都必须要走过)

u->v+n 费用w,流量1  (代表可以移动到那个点)

S->i+n 费用a[i],流量1 (代表从这个点瞬移)

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 int tot,go[200005],next[200005],first[200005],cost[200005],flow[200005];
 7 int op[200005],dis[200005],c[200005],vis[200005],edge[200005],from[200005];
 8 int S,T,n,m,ans;
 9 int read(){
10     char ch=getchar();int t=0,f=1;
11     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
12     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
13     return t*f;
14 }
15 void insert(int x,int y,int z,int l){
16     tot++;
17     go[tot]=y;
18     next[tot]=first[x];
19     first[x]=tot;
20     flow[tot]=z;
21     cost[tot]=l;
22 }
23 void add(int x,int y,int z,int l){
24     insert(x,y,z,l);op[tot]=tot+1;
25     insert(y,x,0,-l);op[tot]=tot-1;
26 }
27 bool spfa(){
28     for (int i=S;i<=T;i++)
29      dis[i]=0x3f3f3f3f,vis[i]=0;
30     int h=1,t=1;c[1]=S;vis[S]=1;dis[S]=0;
31     while (h<=t){
32         int now=c[h++];
33         for (int i=first[now];i;i=next[i]){
34             int pur=go[i];
35             if (dis[pur]>dis[now]+cost[i]&&flow[i]){
36                 dis[pur]=dis[now]+cost[i];
37                 edge[pur]=i;
38                 from[pur]=now;
39                 if (vis[pur]) continue;
40                 vis[pur]=1;
41                 c[++t]=pur;
42             }
43         }
44         vis[now]=0;
45     }
46     return dis[T]!=0x3f3f3f3f;
47 }
48 void updata(){
49     int mn=0x7ffffff;
50     for (int i=T;i!=S;i=from[i]){
51         mn=std::min(mn,flow[edge[i]]);
52     }
53     for (int i=T;i!=S;i=from[i]){
54         ans+=mn*cost[edge[i]];
55         flow[edge[i]]-=mn;
56         flow[op[edge[i]]]+=mn;
57     }
58 }
59 int main(){
60     n=read();m=read();
61     S=0;T=n+n+1;
62     for (int i=1;i<=n;i++)
63      add(S,i,1,0);
64     for (int i=1;i<=n;i++){
65         int x=read();
66         add(S,i+n,1,x);
67     }
68     for (int i=1;i<=n;i++)
69         add(i+n,T,1,0);
70     while (m--){
71         int u=read(),v=read(),w=read();
72         if (u>v) std::swap(u,v);
73         add(u,v+n,1,w);
74     }    
75     ans=0;
76     while (spfa()) updata();
77     printf("%d\n",ans);
78 }

 

posted @ 2016-06-24 20:18  GFY  阅读(190)  评论(0编辑  收藏  举报