1. 程式人生 > >[tyvj-2054][Nescafé29]四葉草魔杖

[tyvj-2054][Nescafé29]四葉草魔杖

str ins head 一次 道理 max clu std spfa

lyd講的最小生成樹的題。
道理我都懂,費用流多好寫,又好調。但和一般費用流不一樣的就是它走過一次後費用需調成0,但是再等回流,就恢復原狀即可。

#include <queue>
#include <cstring>
#include <iostream>
#include <cstdio>
using namespace std;
const int N=5050,S=0,T=5005,inf=0x3f3f3f3f;
int n,m,a[N],sum,ecnt=1,head[N],dis[N],from[N];
bool inq[N];
struct Edge {
    int to,nxt,val,cost,from;
} e[1000010],fb[1000010];
void add(int bg,int ed,int val,int cost) {
    e[++ecnt].cost=cost;e[ecnt].from=bg;e[ecnt].nxt=head[bg];e[ecnt].to=ed;
    e[ecnt].val=val;head[bg]=ecnt;fb[ecnt]=e[ecnt];
}
void insert(int bg,int ed,int val,int cost) {
    add(bg,ed,val,cost);
    add(ed,bg,0,cost);
}
queue<int>q;
bool spfa() {
    q.push(S);
    std::memset(dis,0x3f,sizeof dis);
    std::memset(inq,0,sizeof inq);
    dis[S]=0;
    inq[S]=1;
    while(!q.empty()) {
        int u=q.front();
        q.pop();
        inq[u]=0;
        for(int i=head[u],v; i; i=e[i].nxt) {
            v=e[i].to;
            if(dis[v]>dis[u]+e[i].cost&&e[i].val) {
                dis[v]=dis[u]+e[i].cost;
                from[v]=i;
                if(!inq[v]) q.push(v),inq[v]=1;
            }
        }
    }
    return dis[T]!=inf;
}
void min(int &x,int y) {x=x<y?x:y;}
int mincost,maxflow;
void mcf() {
    int x=inf,i=from[T];
    while(i) {min(x,e[i].val);i=from[e[i].from];}
    i=from[T];maxflow+=x;
    while(i) {
        e[i].val-=x;
        e[i^1].val+=x;
        mincost+=x*e[i].cost;
        if(e[i].val!=inf) {e[i].cost=0;e[i^1].cost=0;}
        else{e[i].cost=fb[i].cost;e[i^1].cost=fb[i^1].cost;}
        i=from[e[i].from];
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1,x;i<=n;i++) {
        scanf("%d",&a[i]);
        if(a[i]>0)insert(S,i,a[i],0),sum+=a[i];
        else if(a[i]<0)insert(i,T,-a[i],0);
    }
    for(int i=1,s,t,x;i<=m;i++) scanf("%d%d%d",&s,&t,&x),add(++s,++t,inf,x),add(t,s,inf,x);//註意
    while(spfa()) mcf();
    if(maxflow==sum){
        mincost=0;
        for(int i=2;i<=ecnt;i++) {if(e[i].val&&e[i].val!=inf) mincost+=fb[i].cost;}
        cout<<mincost/2;
        return 0;
    }
    puts("Impossible");
}

[tyvj-2054][Nescafé29]四葉草魔杖