【BZOJ】【1927】【SDOI2010】星际竞速

网络流/费用流


  比较简单的一题,对于每个星球,将它拆成两个点,然后二分图建模:左部结点与S相连,流量为1费用为0;右部结点与T相连,流量为1费用为0;对于每条航道x->y,连边x->y+n,流量为1,费用为w[i]。

  那么瞬移到某个星球呢?直接连S->n+i,容量为1费用为a[i]。

(建图描述的已经比较清晰了,我就不给大家配图了,自己手画一下就行,很简单的)

  因为是最大流,所以每个星球一定都经过了(每个右部结点都流过了),而每个星球都是从花费最少的那条路径过来的!

  这题由于每个星球都必须经过,且有瞬移的存在,所以其实就是一个贪心,找出到达每个点的最小代价即可(这里的到达就走一步……比如星球4可以从星球2过来,那么就光考虑瞬移a[4]和由2过来的航道w[i]这两个权值即可)

  1 /**************************************************************
  2     Problem: 1927
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:3148 ms
  7     Memory:5988 kb
  8 ****************************************************************/
  9  
 10 //BZOJ 1927
 11 #include<vector>
 12 #include<cstdio>
 13 #include<cstring>
 14 #include<cstdlib>
 15 #include<iostream>
 16 #include<algorithm>
 17 #define rep(i,n) for(int i=0;i<n;++i)
 18 #define F(i,j,n) for(int i=j;i<=n;++i)
 19 #define D(i,j,n) for(int i=j;i>=n;--i)
 20 #define pb push_back
 21 using namespace std;
 22 inline int getint(){
 23     int v=0,sign=1; char ch=getchar();
 24     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
 25     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
 26     return v*sign;
 27 }
 28 const int N=1610,M=200000,INF=~0u>>2;
 29 typedef long long LL;
 30 /******************tamplate*********************/
 31 int a[N],n,m,ans;
 32 struct edge{int from,to,v,c;};
 33 struct Net{
 34     edge E[M];
 35     int head[N],next[M],cnt;
 36     void ins(int x,int y,int z,int c){
 37         E[++cnt]=(edge){x,y,z,c};
 38         next[cnt]=head[x]; head[x]=cnt;
 39     }
 40     void add(int x,int y,int z,int c){
 41         ins(x,y,z,c); ins(y,x,0,-c);
 42     }
 43     int from[N],Q[M],d[N],S,T;
 44     bool inq[N],sign;
 45     bool spfa(){
 46         int l=0,r=-1;
 47         F(i,1,T) d[i]=INF;
 48         d[S]=0; Q[++r]=S; inq[S]=1;
 49         while(l<=r){
 50             int x=Q[l++];
 51             inq[x]=0;
 52             for(int i=head[x];i;i=next[i])
 53                 if(E[i].v>0 && d[x]+E[i].c<d[E[i].to]){
 54                     d[E[i].to]=d[x]+E[i].c;
 55                     from[E[i].to]=i;
 56                     if (!inq[E[i].to]){
 57                         Q[++r]=E[i].to;
 58                         inq[E[i].to]=1;
 59                     }
 60                 }
 61         }
 62         return d[T]!=INF;
 63     }
 64     void mcf(){
 65         int x=INF;
 66         for(int i=from[T];i;i=from[E[i].from])
 67             x=min(x,E[i].v);
 68         for(int i=from[T];i;i=from[E[i].from]){
 69             E[i].v-=x;
 70             E[i^1].v+=x;
 71         }
 72         ans+=x*d[T];
 73     }
 74     void init(){
 75         n=getint(); m=getint(); cnt=1;
 76         S=0; T=n*2+1;
 77         F(i,1,n){
 78             a[i]=getint();
 79             add(S,n+i,1,a[i]);
 80             add(S,i,1,0);
 81             add(n+i,T,1,0);
 82         }
 83         int x,y,z;
 84         F(i,1,m){
 85             x=getint(); y=getint(); z=getint();
 86             if (x>y) swap(x,y);
 87             add(x,y+n,1,z);
 88         }
 89         while(spfa()) mcf();
 90         printf("%d
",ans);
 91     }
 92 }G1;
 93 int main(){
 94 #ifndef ONLINE_JUDGE
 95     freopen("1927.in","r",stdin);
 96     freopen("1927.out","w",stdout);
 97 #endif
 98     G1.init();
 99     return 0;
100 }
View Code
原文地址:https://www.cnblogs.com/Tunix/p/4347930.html