POJ 3436 ACM Computer Factory 【网络流 你妹的建图 竟然还要输出解集】

题面略去。附上链接:http://poj.org/problem?id=3436

若A点输出满足B点的输入,则连一条从A点到B点的有向边,容量正无穷;若某点无输入限制,则连源点到该点;若某点无输出限制,则连该点到汇点。
而对于点权,则拆点,赋容量为点权。
最大流之。
恶心的输出解部分,记录有意义的点的连边情况,流完之后判断流量改变以统计解集。(偷懒想统计反边。。发现有问题,估计是蛋疼的下标写错了)

代码:
#include <iostream>
#include 
<cstdio>
#include 
<cstring>
using namespace std;
#define maxn 105
#define maxm 5500
#define maxnum 2600
#define maxp 15
const int inf = ~0u >> 1;
struct edge
{
    
int p,next,val,anti;
    edge(){}
    edge(
int _p,int _n,int _v,int _a):p(_p),next(_n),val(_v),anti(_a){}
}e[maxm];
int flow[maxn],pre[maxn],cnt[maxn],d[maxn],v[maxn],path[maxn],arc[maxn];
int tot,P,n,N,Count;
void init()
{
    tot 
= 0;
    Count 
= 0;
    fill(v,v 
+ n + 1,-1);
    memset(cnt,
0,sizeof(cnt));
    memset(d,
0,sizeof(d));
    cnt[
0= n + 1;
}
void add(int p,int q,int val)
{
    e[tot] 
= edge(q,v[p],val,tot + 1);
    v[p] 
= tot++;
    e[tot] 
= edge(p,v[q],0,tot - 1);
    v[q] 
= tot++;
}
int mflow()
{
    
int s = 0,t = n;
    
int i,k,loc,least,sum,now;
    
bool flag;
    
for(int i = 0;i <= n;i++)arc[i] = v[i];
    
for(sum = 0,i = s,now = inf;d[s] < n + 1;)
    {
        flow[i] 
= now;
        
for(flag = false,k = arc[i];~k;k = e[k].next)
        {
            
if(e[k].val && d[i] == d[e[k].p] + 1)
            {
                now 
= min(e[k].val,now);
                pre[e[k].p] 
= i;
                path[e[k].p] 
= k;
                arc[i] 
= k;
                i 
= e[k].p;
                
if(i == t)
                {
                    
for(sum += now;i != s;i = pre[i])
                    {
                        e[path[i]].val 
-= now;
                        e[path[i] 
^ 1].val += now;
                    }
                    now 
= inf;
                }
                flag 
= true;
                
break;
            }
        }
        
if(!flag)
        {
            
for(least = n + 1,k = v[i];~k;k = e[k].next)
            {
                
if(e[k].val && d[e[k].p] < least)
                {
                    least 
= d[e[k].p];
                    loc 
= k;
                }
            }
            cnt[d[i]]
--;
            
if(cnt[d[i]] == 0)
                
break;
            arc[i] 
= loc;
            d[i] 
= least + 1;
            cnt[d[i]]
++;
            
if(i != s)
            {
                i 
= pre[i];
                now 
= flow[i];
            }
        }
    }
    
return sum;
}
int line[maxnum],from[maxnum],to[maxnum],cost[maxnum];
int in[maxn][maxp],out[maxn][maxp];
int main()
{
    scanf(
"%d %d",&P,&N);
    n 
= 2 * N + 1;
    init();
    
for(int i = 1;i <= N;i++)
    {
        
int val;
        scanf(
"%d",&val);
        add(i,i 
+ N,val);
        
for(int j = 0;j < P;j++)
            scanf(
"%d",&in[i][j]);
        
for(int j = 0;j < P;j++)
            scanf(
"%d",&out[i][j]);
    }
    
for(int i = 1;i <= N;i++)
    {
        
bool flag = true;
        
for(int j = 0;j < P;j++)
        {
            
if(in[i][j] == 1)
            {
                flag 
= false;
                
break;
            }
        }
        
if(flag)
            add(
0,i,inf);
        flag 
= true;
        
for(int j = 0;j < P;j++)
        {
            
if(out[i][j] == 0)
            {
                flag 
= false;
                
break;
            }
        }
        
if(flag)
            add(i 
+ N,n,inf);
    }
    
for(int i = 1;i <= N;i++)
    {
        
for(int j = 1;j <= N;j++)
        {
            
bool flag = true;
            
for(int k = 0;k < P;k++)
            {
                
if(out[i][k] == in[j][k] || in[j][k] == 2)
                    
continue;
                flag 
= false;
                
break;
            }
            
if(flag)
            {
                line[Count] 
= tot;
                cost[Count] 
= inf;
                add(i 
+ N,j,inf);
                from[Count] 
= i;
                to[Count
++= j;
            }
        }
    }
    
int ans = mflow();
    
int md = 0;
    
if(ans)
    {
        
for(int i = 0;i < Count;i++)
        {
            
if(cost[i] - e[line[i]].val)
                md
++;
        }
    }
    printf(
"%d %d\n",ans,md);
    
if(!md)
        
return 0;
    
for(int i = 0;i < Count;i++)
        
if(cost[i] - e[line[i]].val)
            printf(
"%d %d %d\n",from[i],to[i],cost[i] - e[line[i]].val);
}

posted on 2011-08-06 19:27 BUPT-[aswmtjdsj] @ Penalty 阅读(441) 评论(0)  编辑 收藏 引用 所属分类: 网络流POJ Solution Report


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2011年8月>
31123456
78910111213
14151617181920
21222324252627
28293031123
45678910

导航

统计

常用链接

留言簿(1)

随笔分类(150)

随笔档案(71)

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜