[题解]NOI 2008 志愿者招募

线性规划 -> 费用流

自己没想出来,然后参看了大牛的博客,长跪不起啊。。

http://www.byvoid.com/blog/noi-2008-employee/

下面贴出我自己的程序:

View Code
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<queue>
  5 using namespace std;
  6 #define MAXN 1020
  7 #define MAXM 10020
  8 #define INF 1234567890LL
  9 #define maxm (MAXN*2+MAXM)*2
 10 struct node
 11 {
 12     int v;
 13     int cap,cost;
 14     node *next,*back;
 15 };
 16 node edge[maxm];
 17 node *cnt=&edge[0];
 18 node *adj[MAXN];
 19 int n,m;
 20 int P[MAXN];
 21 int S,T,N;
 22 int Aug[MAXN],dist[MAXN],Prev[MAXN];
 23 bool vis[MAXN];
 24 inline void Get_int(int &Ret)
 25 {
 26     char ch;
 27     bool flag=false;
 28     for(;ch=getchar(),ch<'0'||ch>'9';)
 29         if(ch=='-')
 30             flag=true;
 31     for(Ret=ch-'0';ch=getchar(),ch>='0'&&ch<='9';Ret=Ret*10+ch-'0');
 32     flag&&(Ret=-Ret);
 33 }
 34 inline void Addedge(int u,int v,int cap,int cost)
 35 {
 36     node *p=++cnt;node *q=++cnt;
 37     p->v=v;q->v=u;
 38     p->cap=cap;q->cap=0;
 39     p->cost=cost;q->cost=-cost;
 40     p->next=adj[u];q->next=adj[v];
 41     adj[u]=p;adj[v]=q;
 42     p->back=q;q->back=p;
 43 }
 44 void Read()
 45 {
 46     Get_int(n),Get_int(m);
 47     S=0,T=n+2;
 48     N=n+3;
 49     int i,j,st,ed,c;
 50     for(i=1;i<=n;i++)
 51         Get_int(P[i]);
 52     for(i=1;i<=m;i++)
 53     {
 54         Get_int(st),Get_int(ed),Get_int(j);
 55         Addedge(st,ed+1,INF,j);
 56     }
 57     for(i=1;i<=n+1;i++)
 58     {
 59         c=P[i]-P[i-1];
 60         if(c>=0)
 61             Addedge(S,i,c,0);
 62         else
 63             Addedge(i,T,-c,0);
 64         if(i>1)
 65             Addedge(i,i-1,INF,0);
 66     }
 67 }
 68 bool Spfa()
 69 {
 70     int i,u,v;
 71     queue <int > q;
 72     for(i=S;i<=T;i++)
 73         dist[i]=INF,vis[i]=false,Aug[i]=Prev[i]=0;
 74     dist[S]=0,Aug[S]=INF,Prev[S]=-1;
 75     q.push(S);
 76     vis[S]=true;
 77     while(!q.empty())
 78     {
 79         u=q.front();q.pop();
 80         vis[u]=false;
 81         for(node *p=adj[u];p;p=p->next)
 82         {
 83             v=p->v;
 84             if(p->cap<=0)
 85                 continue;
 86             if(dist[u]+p->cost<dist[v])
 87             {
 88                 dist[v]=dist[u]+p->cost;
 89                 Prev[v]=u;
 90                 Aug[v]=min(Aug[u],p->cap);
 91                 if(!vis[v])
 92                 {
 93                     q.push(v);
 94                     vis[v]=true;
 95                 }
 96             }
 97         }
 98     }
 99     return dist[T]!=INF;
100 }
101 void Work()
102 {
103     int Min_cost=0;
104     int u,v;
105     while(Spfa())
106     {
107         Min_cost+=dist[T]*Aug[T];
108         v=T;
109         while(v!=S)
110         {
111             u=Prev[v];
112             for(node *p=adj[u];p;p=p->next)
113                 if(p->v==v&&dist[u]+p->cost==dist[v]&&p->cap>=Aug[T])
114                 {
115                     p->cap-=Aug[T];
116                     p->back->cap+=Aug[T];
117                     break;
118                 }
119             v=u;
120         }
121     }
122     printf("%d\n",Min_cost);
123 }
124 int main()
125 {
126     Read();
127     Work();
128     return 0;
129 }

 

posted @ 2013-03-06 19:52  zyy是一只超级大沙茶  阅读(229)  评论(0编辑  收藏  举报