bzoj1927星际竞速

 

#include<cstdio> 
#include<cmath> 
#include<cstdlib> 
#include<algorithm> 
#include<cstring> 
#include<queue> 
#define N 1005*2 
#define M 20005+800*3 
using namespace std; 
const int inf=0x3f3f3f3f; 
int n,m,S,T; 
int head[N],tot,dis[N],pre[N],now[N]; 
bool b[N]; 
inline int read() 
{ 
    int ans;char ch; 
    while ((ch=getchar())<'0'||ch>'9') ;ans=ch-'0'; 
    while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0'; 
    return ans; 
} 
struct aa 
{ 
    int to,pre,flow,cap,c; 
}edge[M*10]; 
void addedge(int u,int v,int f,int c) 
{ 
    edge[++tot].to=v;edge[tot].pre=head[u];edge[tot].cap=f;edge[tot].c=c;head[u]=tot; 
    edge[++tot].to=u;edge[tot].pre=head[v];edge[tot].cap=0;edge[tot].c=-c;head[v]=tot; 
} 
  
bool spfa() 
{ 
    for (int i=1;i<=n*2+5;i++) dis[i]=inf;
    memset(pre,0,sizeof(pre)); 
    memset(now,0,sizeof(now)); 
    memset(b,false,sizeof(b)); 
    dis[S]=0; 
    queue<int> q;q.push(S); 
    while (!q.empty()) 
    { 
        int u=q.front();q.pop();b[u]=false; 
        for (int i=head[u];i;i=edge[i].pre) 
        if (edge[i].cap>edge[i].flow&&dis[edge[i].to]>dis[u]+edge[i].c) 
        { 
            dis[edge[i].to]=dis[u]+edge[i].c; 
            pre[edge[i].to]=u; 
            now[edge[i].to]=i; 
            if (!b[edge[i].to]) b[edge[i].to]=true,q.push(edge[i].to); 
        } 
    } 
    return dis[T]!=inf; 
} 
int work() 
{ 
    int ans=0; 
    while (spfa()) 
    { 
        int flow=inf; 
        for (int i=T;i!=S;i=pre[i]) 
        flow=min(flow,edge[now[i]].cap-edge[now[i]].flow); 
        ans+=flow*dis[T]; 
        for (int i=T;i!=S;i=pre[i]) 
        edge[now[i]].flow+=flow,edge[((now[i]-1)^1)+1].flow-=flow; 
    } 
    return ans; 
} 
  
int main() 
{ 
    n=read(),m=read(); 
    S=n*2+1,T=S+1; 
    int x,y,z; 
    for (int i=1;i<=n;i++) 
    { 
        x=read(); 
        addedge(S,n+i,1,x); 
    } 
    for (int i=1;i<=m;i++) 
    { 
        x=read(),y=read(),z=read(); 
        if (x>y) swap(x,y); 
        addedge(x,y+n,1,z); 
    } 
    for (int i=1;i<=n;i++) 
    { 
        addedge(S,i,1,0); 
        addedge(i+n,T,1,0); 
    } 
    printf("%d",work()); 
    return 0; 
}


总结

1:一定要注意细节,很多时候小数据是处理不出细节错误的,例如(i-1)^1)+1,加和异或的位置不要错

2:最小路径覆盖的费用流变种,注意积累几点题型

3:memset的inf和普通赋值的inf不一样,尤其是在不同的编译器上!!,所以费用流之类当中的dis赋初值都要循环赋值!!!!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值