【网络流24题】餐巾计划问题
题目:
https://www.luogu.org/problemnew/show/P1251
题解:
原来的想法不行:算费用的时候算的是一条餐巾的,但对于重复使用多天的餐巾不公平,因为他们的费用肯定比用一次的大,但是它们贡献也大。
两种想法:
->平均费用 不可做。
->这一次费用 可做。
嘿嘿,还挺有意思的。
#include<cstdio> #include<cstring> #include<iostream> #include<vector> #include<queue> #include<cstdlib> #define LL long long #define N 10000 #define INF 1000000007 #define S 0 #define T (2*n+1) #define ri register int using namespace std; int n,cc; int r[N],p0,t1,p1,t2,p2; int cr(int x){ return 2*n+x+1; } struct graph { vector<int> to,w,c; vector<int> ed[N]; LL dis[N]; int cur[N]; bool vis[N]; void add_edge(int a,int b,int aw,int ac) { to.push_back(b); w.push_back(aw); c.push_back(ac); ed[a].push_back(to.size()-1); to.push_back(a); w.push_back(0); c.push_back(-ac); ed[b].push_back(to.size()-1); } bool spfa() { memset(dis,0x2f,sizeof(dis)); memset(vis,0,sizeof(vis)); queue<int> q; dis[S]=0;q.push(S);vis[S]=1; while (!q.empty()) { int x=q.front(); q.pop(); //printf("%d %d %lld\n",cc,x,dis[x]); for (ri i=0;i<ed[x].size();i++) { int e=ed[x][i]; if (dis[to[e]]>dis[x]+c[e] && w[e]) { dis[to[e]]=dis[x]+c[e]; if (!vis[to[e]]) vis[to[e]]=1,q.push(to[e]); } } vis[x]=0; } return dis[T]<INF; } int dfs(int x,int lim) { if (x==T || !lim) return lim; LL sum=0; vis[x]=1; for (ri &i=cur[x];i<ed[x].size();i++) { int e=ed[x][i]; if (dis[x]+c[e]==dis[to[e]] && w[e] && !vis[to[e]]) { int f=dfs(to[e],min(lim,w[e])); w[e]-=f; w[1^e]+=f; lim-=f; sum+=f; if (!lim) return sum; } } return sum; } LL zkw() { LL ret=0; cc=1; while (spfa()) { memset(vis,0,sizeof(vis)); memset(cur,0,sizeof(cur)); int t=dfs(S,INF); ++cc; ret+=t*dis[T]; } return ret; } } G; int main() { scanf("%d",&n); for (ri i=1;i<=n;i++) scanf("%d",&r[i]); scanf("%d %d %d %d %d",&p0,&t1,&p1,&t2,&p2); for (ri i=1;i<=n;i++) G.add_edge(S,n+i,r[i],0); for (ri i=1;i<=n;i++) G.add_edge(i,T,r[i],0); for (ri i=1;i<n;i++) G.add_edge(n+i,n+i+1,INF,0); for (ri i=1;i<=n;i++) { if (i+t1<=n) G.add_edge(n+i,i+t1,INF,p1); if (i+t2<=n) G.add_edge(n+i,i+t2,INF,p2); } for (ri i=1;i<=n;i++) G.add_edge(S,i,INF,p0); printf("%lld\n",G.zkw()); return 0; }