zoukankan      html  css  js  c++  java
  • [bzoj1927]星际竞速

    考虑没有爆发,那么相当于是带权最小不可交路径覆盖,由于只能从编号小的到编号大的,因此一定是DAG,而DAG的最小路径覆盖可以拆点并跑最大流,那么带权的只需要跑费用流即可(S向i连(1,0)的边,i’向T连(1,0)的边,i向j’连(1,t)的边,其中i->j有时间为t的边)。
    考虑爆发操作,相当于让任意两点之间都能够新增一条边,但这样跑边数太多,可以直接从S连向i’(1,ai)的边(ai表示i爆发的代价)即可。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 2005
     4 struct ji{
     5     int nex,to,len,cost;
     6 }edge[N*20];
     7 queue<int>q;
     8 int E,n,m,t,x,y,head[N],d[N],vis[N],from[N];
     9 void add(int x,int y,int z,int w){
    10     edge[E].nex=head[x];
    11     edge[E].to=y;
    12     edge[E].len=z;
    13     edge[E].cost=w;
    14     head[x]=E++;
    15     if (E&1)add(y,x,0,-w);
    16 }
    17 bool spfa(){
    18     memset(d,0x3f,sizeof(d));
    19     memset(vis,0,sizeof(vis));
    20     q.push(0);
    21     d[0]=0;
    22     while (!q.empty()){
    23         int k=q.front();
    24         q.pop();
    25         vis[k]=0;
    26         for(int i=head[k];i!=-1;i=edge[i].nex){
    27             int v=edge[i].to;
    28             if ((edge[i].len)&&(d[v]>d[k]+edge[i].cost)){
    29                 d[v]=d[k]+edge[i].cost;
    30                 from[v]=i;
    31                 if (!vis[v]){
    32                     vis[v]=1;
    33                     q.push(v);
    34                 }
    35             }
    36         }
    37     }
    38     return d[t]<0x3f3f3f3f;
    39 }
    40 int dinic(){
    41     int ans=0;
    42     while (spfa()){
    43         ans+=d[t];
    44         for(int i=t;i;i=edge[from[i]^1].to){
    45             edge[from[i]].len--;
    46             edge[from[i]^1].len++;
    47         }
    48     }
    49     return ans;
    50 }
    51 int main(){
    52     scanf("%d%d",&n,&m);
    53     memset(head,-1,sizeof(head));
    54     for(int i=1;i<=n;i++){
    55         scanf("%d",&t);
    56         add(0,i,1,0);
    57         add(0,i+n,1,t);
    58         add(i+n,2*n+1,1,0);
    59     }
    60     for(int i=1;i<=m;i++){
    61         scanf("%d%d%d",&x,&y,&t);
    62         if (x>y)swap(x,y); 
    63         add(x,y+n,1,t);
    64     }
    65     t=2*n+1;
    66     printf("%d",dinic());
    67 }
    View Code
  • 相关阅读:
    1084: 计算两点间的距离(多实例测试)
    1083: 数值统计(多实例测试)
    回文数的判断
    1082: 敲7(多实例测试)
    BZOJ 1303 [CQOI2009]中位数图
    计蒜客 Yingchuan Online F题 (Floyd 变形)
    并查集入门题
    常见错点
    单调队列入门题
    线段树入门题
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11362604.html
Copyright © 2011-2022 走看看