noi2008 志愿者招募(1)

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<limits.h>
#define inf 0x7fffffff
#define N 1002
#define maxne 100002
#include<queue>
using namespace std;
typedef long long ll;
struct data{  int s,t,c;};
struct edge{ int nxt,point,v; int remain,cost;};
int mincost,max_flow;
int n,m,start,end,cnt;
data vol[N*10+5];
edge e[maxne+5];
int need[N+5],lastedge[maxne+5],dis[N+5];
bool used[N+5];
inline void addedge(int u1,int v1,int w1,int w2){
  e[++cnt].nxt=e[u1].point;e[u1].point=cnt;e[cnt].v=v1;e[cnt].remain=w1;e[cnt].cost=w2;}
inline void insert(int u1,int v1,int w1,int w2){ 
addedge(u1,v1,w1,w2); addedge(v1,u1,0,-w2); }
inline int getnum(){
    char c; int num;
    while (!isdigit(c=getchar()));
    num=c-'0';
    while (isdigit(c=getchar())) num=num*10+c-'0';
    return num;
}

void init(){
    cnt=-1;
    for (int i=0;i<=maxne;++i) e[i].point=e[i].nxt=-1;
    n=getnum(); m=getnum();
    start=n+2; end=n+3; need[0]=need[n+1]=0;
    for (int i=1;i<=n;++i) need[i]=getnum();
    for (int i=1;i<=m;++i) vol[i].s=getnum(), vol[i].t = getnum() , vol[i].c = getnum();
}

void make_it(){
    for (int i = 1;i <= n+1; ++i){
      int delta=need[i]-need[i-1];
      if (delta>=0) insert(start,i,delta,0);
      else insert(i,end,-delta,0);}
    for (int i = 1;i <= m; ++i) insert( vol[i].s, vol[i].t+1, inf ,vol[i].c );
    for (int i = 2;i <= n+1; ++i) insert( i, i-1, inf, 0);
}

inline int add_it(int s,int t){
    int now=t; int add1=inf;
    while (now != s){
        add1=min(add1,e[lastedge[now]].remain);
        now = e[lastedge[now]^1].v;
    }
    now=t;
    while (now != s){
        e[lastedge[now]].remain-=add1;
        e[lastedge[now]^1].remain+=add1;
        now=e[lastedge[now]^1].v;
    }
    return add1;
}

inline bool spfa(int s,int t,int &max_flow,int &mincost){
    queue<int>q;
    for (int i=0;i<=N+5;++i) dis[i]=inf;
    memset(used,0,sizeof(used));
     used[s]=1; dis[s]=0; q.push(s);
    while (!q.empty()){
        int x=q.front(); q.pop(); 
        for (int p = e[x].point; p != -1;p = e[p].nxt)
          if ( e[p].remain&&(dis[x] + e[p].cost < dis[e[p].v])){
               lastedge[e[p].v]=p;
               dis[e[p].v]=dis[x]+e[p].cost;
               if (!used[e[p].v]) { used[e[p].v]=1; q.push(e[p].v);}
          }
          used[x]=0;
    }
    if (dis[t] == inf) return 0;
    int add_flow = add_it(s,t);
    max_flow += add_flow;
    mincost += add_flow * dis[t];
    return 1;
}

void mfmc(){
    max_flow = mincost = 0;
    while (spfa(start,end,max_flow,mincost));
}

void doit(){
    for (int i=1;i<=n+3;++i){
        int num=0;
        cout<<endl;
        for (int p=e[i].point;p!=-1;p=e[p].nxt){
         ++num; cout<<e[p].v<<" "; if (num>1000) {
         cout<<i;break;}
    }
    }
}

int main(){
    init();
    make_it();
    // cout<<cnt<<endl;
    //doit();
    mfmc();
    cout<<mincost;
    fclose(stdin); fclose(stdout);
    return 0;
}

竟然看错了数据范围调了很久很久很久很久,,,,啊,,,看题一定要仔细,,出现奇怪问题时一般都是有错的,要不是算法本身有错,要不是编错了,,可能爆了,,,
几种理解:1.byvoid 2.线性规划 3.填坑算法(hdu3947) (1,2都是流量平衡构图法) 4.单纯形法 5.po姐http://blog.csdn.net/popoqqq/article/details/44310605
填坑:http://www.xuebuyuan.com/955080.html

你可能感兴趣的:(noi2008 志愿者招募(1))