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

[kuangbin带你飞]专题十一 网络流 A POJ - 3436

2017-04-19 21:36 423 查看
题目地址:https://vjudge.net/contest/68128#problem/A

思路:添加一个超级汇点一个超级源点,将所有进入状态不含1的点与超级源点相连,将所有输出状态不含0的点与超级汇点相连,将所有输入状态和输出状态可以匹配的点相连。这样建图就可以把问题转化为最大流问题。路径输出判断该条边的流量是否有使用即可。

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN = 100+10;
const int MAXM = 1e6+10;
const int INF = 0x3f3f3f3f;
struct edge{
int u,v,next,cap,flow;
}edge[MAXM];
int tol;
int head[MAXN];
struct pos{
int a[15];
int b[15];
int c;
}m[MAXN];
void init(){
tol=0;
memset(head,-1,sizeof(head));
}

void addedge(int u,int v,int w){
edge[tol].u=u;
edge[tol].v=v;
edge[tol].cap=w;
edge[tol].next=head[u];
//printf("head:%d\n",head[u]);
head[u]=tol++;
edge[tol].u=v;
edge[tol].v=u;
edge[tol].cap=0;
edge[tol].next=head[v];
head[v]=tol++;
}
int dep[MAXN],cur[MAXN],sta[MAXN];

bool bfs(int s,int t){
queue<int>q;
memset(dep,-1,sizeof(dep));
dep[s]=0;
q.push(s);
while(!q.empty()){
int u=q.front();
//printf("%d\n",u);
q.pop();
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
//printf("%d\n",i);
//getchar();
if(edge[i].cap>0 && dep[v]==-1){
dep[v]=dep[u]+1;
if(v==t)
return true;
q.push(v);
}
}
}
return false;
}

int dfs(int a,int b,int s,int t){
int r=0;
if(a==t)
return b;
for(int i=head[a];i!=-1 && r<b;i=edge[i].next){
int u=edge[i].v;
if(edge[i].cap>0 && dep[u]==dep[a]+1){
int x=min(edge[i].cap,b-r);
x=dfs(u,x,s,t);
r+=x;
edge[i].cap-=x;
edge[i^1].cap+=x;
}
}
if(!r)
dep[a]=-2;
return r;
}

int dinic(int s,int t){
int total=0,temp;
while(bfs(s,t)){
// printf("hahaha");
while(temp=dfs(s,INF,s,t))
total+=temp;
// printf("%d\n",total);
}
return total;
}
int p,n;
int main(){
init();
scanf("%d%d",&p,&n);
for(int i=1;i<=n;i++){
scanf("%d",&m[i].c);
for(int j=0;j<p;j++)
scanf("%d",&m[i].a[j]);
for(int j=0;j<p;j++)
scanf("%d",&m[i].b[j]);
}
//超级源点
for(int i=1;i<=n;i++){
bool temp=true;
for(int j=0;j<p;j++){
if(m[i].a[j]==1){
temp=false;
break;
}
}
if(temp)
addedge(0,i,m[i].c);
}
//超级汇点
for(int i=1;i<=n;i++){
bool temp=true;
for(int j=0;j<p;j++){
if(m[i].b[j]==0){
temp=false;
break;
}
}
if(temp)
addedge(i,n+1,m[i].c);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)
continue;
bool temp=true;
for(int k=0;k<p;k++){
if(m[i].b[k]+m[j].a[k]==1){
temp=false;
break;
}
}
if(temp)
addedge(i,j,m[i].c);
}
}
int ans=dinic(0,n+1);
printf("%d ",ans);
int w=0;
for(int i=0;i<tol;i+=2){
if(edge[i].u==0 || edge[i].v==n+1)
continue;
if(edge[i].cap!=m[edge[i].u].c)
w++;
}
printf("%d\n",w);
for(int i=0;i<tol;i+=2){
if(edge[i].u==0 || edge[i].v==n+1)
continue;
if(edge[i].cap!=m[edge[i].u].c)
printf("%d %d %d\n",edge[i].u,edge[i].v,m[edge[i].u].c-edge[i].cap);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: