标签:else www ref rom p12 cas div https void
一,无源网络流的建模
https://www.luogu.org/problemnew/show/P1231
题意,给你n1本书,n2本练习册,n3本答案,给你这些书和答案对应关系,问你最多能组成多少本书册。
由于需要书,练习册,答案三件套才能组成完整书册,将书复制成两份,一份与练习册建立边,一份与答案建立边,
建立源点和汇点,跑一边最大流就能解决
#includeusing namespace std;
const int maxn=100000;
const int INF=0x3fffffff;
struct Dinic
{
struct Edge
{
int from,to,cap,flow;
};
int n,m,s,t;
vectoredges;
vectorint>G[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn];
void AddEdge(int from,int to,int cap)
{
edges.push_back((Edge)
{
from,to,cap,0
});
edges.push_back((Edge)
{
to,from,0,0
});//反向弧
m=edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool BFS()
{
memset(vis,0,sizeof(vis));
queueint>Q;
Q.push(s);
d[s]=0;
vis[s]=1;
while(!Q.empty())
{
int x=Q.front();
Q.pop();
for (int i=0; i)
{
Edge& e=edges[G[x][i]];
if(!vis[e.to]&&e.cap>e.flow)
{
vis[e.to]=1;
d[e.to]=d[x]+1;
Q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int x,int a)//x为当前节点,a为目前为止所有弧的最小流量
{
if(x==t||a==0)return a;
int flow=0,f;
for (int& i=cur[x]; i )
{
Edge& e = edges[G[x][i]];
if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0)//下一层次加1并且残留量不为零
{
e.flow+=f;
edges[G[x][i]^1].flow-=f;
flow+=f;
a-=f;
if(a==0)break;
}
}
return flow;
}
int Maxflow(int s,int t)
{
this->s=s;
this->t=t;
int flow=0;
while(BFS())
{
memset(cur,0,sizeof(cur));
flow+=DFS(s,INF);
}
return flow;
}
};
Dinic dc;
int main()
{
int n1,n2,n3,m1,m2,m3;
scanf("%d %d %d",&n1,&n2,&n3);
scanf("%d",&m1);
for(int i=1; i//练习册指书的边
{
int x,y;
scanf("%d %d",&x,&y);
dc.AddEdge(y,x+n2,1);
}
scanf("%d",&m2);
for(int i=1; i//书指向答案的边
{
int x,y;
scanf("%d %d",&x,&y);
dc.AddEdge(x+n2+n1,2*n1+n2+y,1);
}
for(int i=1; i//建立源点指向练习册的边
{
dc.AddEdge(0,i,1);
}
for(int i=1; i//建立书指向书的边
{
dc.AddEdge(n2+i,n2+n1+i,1);
}
int end=n1*2+n2+n3+1;
for(int i=1; i//建立书指向终点的边
{
dc.AddEdge(n2+2*n1+i,end,1);
}
printf("%d",dc.Maxflow(0,end));
return 0;
}
二,建立二分图跑网络流
题意,给你个二分图,每次选择一条边会给每个点加一个度,问能否使得点的度的范围在[l,r]之间。
https://nanti.jisuanke.com/t/31447
#include
#include
#include
#include
using namespace std;
const int maxn=20010;
const int N=0x3f3f3f3f;
const int INF=0x3fffffff;
int degree[maxn];
int u[maxn];
int v[maxn];
struct Dinic
{
struct Edge
{
int from,to,cap,flow;
};
int n,m,s,t;
vectoredges;
vectorG[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn];
void AddEdge(int from,int to,int cap)
{
edges.push_back((Edge)
{
from,to,cap,0
});
edges.push_back((Edge)
{
to,from,0,0
});//反向弧
m=edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool BFS()
{
memset(vis,0,sizeof(vis));
queueQ;
Q.push(s);
d[s]=0;
vis[s]=1;
while(!Q.empty())
{
int x=Q.front();
Q.pop();
for (int i=0; ie.flow)
{
vis[e.to]=1;
d[e.to]=d[x]+1;
Q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int x,int a)//x为当前节点,a为目前为止所有弧的最小流量
{
if(x==t||a==0)return a;
int flow=0,f;
for (int& i=cur[x]; i0)//下一层次加1并且残留量不为零
{
e.flow+=f;
edges[G[x][i]^1].flow-=f;
flow+=f;
a-=f;
if(a==0)break;
}
}
return flow;
}
int Maxflow(int s,int t)
{
this->s=s;
this->t=t;
int flow=0;
while(BFS())
{
memset(cur,0,sizeof(cur));
flow+=DFS(s,INF);
}
return flow;
}
};
void init()
{
memset(degree,0,sizeof(degree));
return;
}
int main()
{
int cas,i,l,r,minn,maxx,res,sum,n,m,k;
cas=1;
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
init();
scanf("%d%d",&l,&r);
for(i=1; ir&°ree[v[i]]>r)
{
degree[u[i]]--,degree[v[i]]--;
}
}
int source=0,sink=n+m+1;
Dinic dc;
for(i=1; ir&°ree[v[i]]>l) dc.AddEdge(u[i],v[i],1);
else if(degree[v[i]]>r&°ree[u[i]]>l) dc.AddEdge(v[i],u[i],1);
}
sum=0;
for(i=1; ir)
{
dc.AddEdge(source,i,degree[i]-r);
sum+=(degree[i]-r);
}
else if(degree[i]>l)
{
dc.AddEdge(i,sink,degree[i]-l);
}
}
res=dc.Maxflow(source,sink);
if(res==sum) printf("Case %d: Yes\n",cas++);
else printf("Case %d: No\n",cas++);
}
}
else printf("Case %d: No\n",cas++);
}
return 0;
}
三,无源上下界网络流问题
模板题
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314
#include
using namespace std;
const int maxn=100005;
const int INF=0x3fffffff;
struct Dinic
{
struct Edge
{
int from,to,cap,flow;
};
int n,m,s,t;
vectoredges;
vectorG[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn];
void init(int n)
{
for (int i=0; iQ;
Q.push(s);
d[s]=0;
vis[s]=1;
while(!Q.empty())
{
int x=Q.front();
Q.pop();
for (int i=0; ie.flow)
{
vis[e.to]=1;
d[e.to]=d[x]+1;
Q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int x,int a)//x为当前节点,a为目前为止所有弧的最小流量
{
if(x==t||a==0)return a;
int flow=0,f;
for (int& i=cur[x]; i0)//下一层次加1并且残留量不为零
{
e.flow+=f;
edges[G[x][i]^1].flow-=f;
flow+=f;
a-=f;
if(a==0)break;
}
}
return flow;
}
int Maxflow(int s,int t)
{
this->s=s;
this->t=t;
int flow=0;
while(BFS())
{
memset(cur,0,sizeof(cur));
flow+=DFS(s,INF);
}
return flow;
}
};
int d[maxn];
int l[maxn];
Dinic dc;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
dc.init(n);
memset(d,0,sizeof d);
for (int i=0; i0)
{
dc.AddEdge(i,n+1,d[i]);
ss+=d[i];
}
else
dc.AddEdge(0,i,-d[i]);
}
if(dc.Maxflow(0,n+1)==ss)
{
cout
四,二分图,建立源点的有源上下界网络流
题目和上面的二分图一样,解决方法是建立一个源点连向左图,每条边的范围要是[l,r],右图连向汇点,范围一样,左图与右图的边的范围是[0,1],就转化为上面的模板题了。
#include
using namespace std;
const int maxn=100005;
const int INF=0x3fffffff;
struct Dinic
{
struct Edge
{
int from,to,cap,flow;
};
int n,m,s,t;
vectoredges;
vectorG[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn];
void init(int n)
{
for (int i=0; iQ;
Q.push(s);
d[s]=0;
vis[s]=1;
while(!Q.empty())
{
int x=Q.front();
Q.pop();
for (int i=0; ie.flow)
{
vis[e.to]=1;
d[e.to]=d[x]+1;
Q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int x,int a)//x为当前节点,a为目前为止所有弧的最小流量
{
if(x==t||a==0)return a;
int flow=0,f;
for (int& i=cur[x]; i0)//下一层次加1并且残留量不为零
{
e.flow+=f;
edges[G[x][i]^1].flow-=f;
flow+=f;
a-=f;
if(a==0)break;
}
}
return flow;
}
int Maxflow(int s,int t)
{
this->s=s;
this->t=t;
int flow=0;
while(BFS())
{
memset(cur,0,sizeof(cur));
flow+=DFS(s,INF);
}
return flow;
}
};
int d[maxn];
int l[maxn];
Dinic dc;
int main()
{
int n,m,k;
int acm=1;
while(~scanf("%d%d%d",&n,&m,&k))
{
dc.init(n);
int l,r;
scanf("%d%d",&l,&r);
memset(d,0,sizeof d);
for(int i=1; i0)
{
dc.AddEdge(i,n+m+3,d[i]);
ss+=d[i];
}
else
dc.AddEdge(n+m+2,i,-d[i]);
}
dc.AddEdge(n+m+1,0,0x3fffffff);
if(dc.Maxflow(n+m+2,n+m+3)==ss)
{
printf("Case %d: Yes\n",acm++);
}
else
printf("Case %d: No\n",acm++);
}
return 0;
}
白皮书最大流算法连续题
标签:else www ref rom p12 cas div https void
原文地址:https://www.cnblogs.com/Json-Five/p/9748953.html