[题解]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 }