题解:

费用流

拆点

代码:

#include<bits/stdc++.h> 
const int N=40010;  
using namespace std;  
int n,m,l=1,fi[N],ne[N],to[N],v[N],c[N],cnt;
int x,y,z,q[N*2],dis[N],fa[N],Ans,fl[N],flag[N];  
void jb(int x,int y,int V,int C)  
{  
    to[++l]=y;v[l]=V;c[l]=C;ne[l]=fi[x];fi[x]=l;  
    to[++l]=x;v[l]=0;c[l]=-C;ne[l]=fi[y];fi[y]=l;  
}  
bool SPFA()  
{  
    int head=0,tail=1;  
    memset(fl,0x3f,sizeof fl);  
    memset(flag,0,sizeof flag);  
    memset(dis,0x3f,sizeof dis);  
    q[1]=0;fl[0]=1e9;dis[0]=0;  
    while (head!=tail)  
     {  
        head++;
        if (head==N) head=0;  
        x=q[head];flag[x]=0;  
        for (int i=fi[x];i;i=ne[i])  
         {  
            if (dis[to[i]]>dis[x]+c[i]&&v[i]>0)  
             {  
                dis[to[i]]=dis[x]+c[i];  
                fa[to[i]]=i;  
                fl[to[i]]=min(fl[x],v[i]);  
                if (!flag[to[i]])  
                 {  
                    flag[to[i]]=1;  
                    tail++;
                    if (tail==N) tail=0;  
                    q[tail]=to[i];  
                 }  
             }  
         }   
     }  
    return fl[cnt]<1e9;  
}  
void flow()  
{  
    for (int i=cnt;i;i=to[fa[i]^1])  
     {  
        v[fa[i]]-=fl[cnt];  
        v[fa[i]^1]+=fl[cnt];  
        Ans+=c[fa[i]]*fl[cnt];  
     }  
}  
int main()  
{  
    scanf("%d%d",&n,&m);  
    cnt=n+n+1;  
    for (int i=1;i<=n;i++)scanf("%d",&x),jb(0,i+n,1,x);  
    for (int i=1;i<=m;i++)  
     {  
        scanf("%d%d%d",&x,&y,&z);  
        if (x>y) swap(x,y);  
        jb(x,y+n,1,z);  
     }  
    for (int i=1;i<=n;i++)jb(0,i,1,0),jb(i+n,cnt,1,0);  
    while (SPFA())flow();  
    printf("%d\n",Ans);  
}  

 

posted on 2018-02-12 09:54  宣毅鸣  阅读(116)  评论(0编辑  收藏  举报