您的位置:首页 > 理论基础 > 计算机网络

【这是一个可能永远填不完的坑】网络流24题

2018-04-10 21:06 323 查看
  看到那么多大佬都开坑刷题,那我也随波逐流一下。。。虽然保不准什么时候就弃掉了。。

  进度:

6/24

  1、餐巾计划问题(费用流)

  题目传送门:https://www.luogu.org/problemnew/show/P1251

  这道题还是比较思维的。。。(然而说白了都是套路)

  显然我们可以把餐巾使用量看作网络的流量,把花费看作网络的费用。

  这道题主要的难点就在于如何保证每天一定有ai条餐巾用,以及处理干净餐巾的来源与脏餐巾的去向。因为只能通过源汇来控制整个网络的流量(即餐巾的使用量),所以我们可以把使用一条干净餐巾的过程拆成两个部分:(1)把一条干净的餐巾流进汇点;(2)让一条脏餐巾从源点流出。

  于是把一天拆成两个点,一个用来接受脏餐巾,一个用来使用干净的餐巾,然后按题意连边(把脏餐巾洗干净),跑最小费用最大流就行了。

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define ull unsigned long long
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define lowbit(x) (x& -x)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define eps 1e-18
#define maxn 1010
inline ll read(){ll tmp=0; char c=getchar(),f=1; for(;c<'0'||'9'<c;c=getchar())if(c=='-')f=-1; for(;'0'<=c&&c<='9';c=getchar())tmp=(tmp<<3)+(tmp<<1)+c-'0'; return tmp*f;}
inline ll power(ll a,ll b){ll ans=0; for(;b;b>>=1){if(b&1)ans=ans*a%mod; a=a*a%mod;} return ans;}
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline void swap(int &a,int &b){int tmp=a; a=b; b=tmp;}
using namespace std;
struct edge{
int to,nxt,flow;
}e[maxn*maxn*2+4*maxn];
int fir[2*maxn],lv[2*maxn],q[2*maxn];
int n,m,S,T,tot=0;
void add(int x,int y,int flow)
{
e[tot].to=y; e[tot].flow=flow; e[tot].nxt=fir[x]; fir[x]=tot++;
e[tot].to=x; e[tot].flow=0; e[tot].nxt=fir[y]; fir[y]=tot++;
}
int dfs(int now,int flow)
{
if(now==T)return flow;
for(int i=fir[now];~i;i=e[i].nxt)
if(e[i].flow&&lv[e[i].to]==lv[now]+1){
int tmp=dfs(e[i].to,min(flow,e[i].flow));
e[i].flow-=tmp; e[i^1].flow+=tmp;
if(tmp)return tmp;
}
return 0;
}
int dinic()
{
int i,ans=0;
while(1){
for(i=0;i<=T;i++)lv[i]=0;
int h=1,t=1; q[1]=S; lv[S]=1;
while(h<=t){
for(i=fir[q[h]];~i;i=e[i].nxt)
if(e[i].flow&&!lv[e[i].to]){
q[++t]=e[i].to; lv[e[i].to]=lv[q[h]]+1;
}
++h;
}
if(!lv[T])return ans;
int k=dfs(S,inf);
while(k)ans+=k,k=dfs(S,inf);
}
}
int main()
{
memset(fir,255,sizeof(fir));
n=read(); m=read(); S=0; T=n+m+1;
int cnt=0;
for(int i=1;i<=n;i++){
int k=read(); add(S,i,k); cnt+=k;
}
for(int i=1;i<=m;i++){
int p=read();
while(p--)add(read(),n+i,1);
add(n+i,T,1);
}
int ans=dinic();
if(ans<cnt)printf("No Solution!\n");
else{
for(int i=1;i<=n;i++){
printf("%d:",i);
for(int j=fir[i];~j;j=e[j].nxt)
if(!e[j].flow&&e[j].to!=S)
printf("%d ",e[j].to-n);
printf("\n");
}
}
}


View Code

 To be continued……
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐