POJ 3189 Steady Cow Assignment [二分+枚举+最大流]

链接:http://poj.org/problem?id=3189
一开始理解错题意了,以为是使得每个牛棚中的喜好度差值最小。。。这果断是神题吧,O(20^20 * log(20) * O(网络流))的复杂度。坑爹啊。
后来发现是全局(全牛棚)的喜好度差值最小。。那么果断枚举上界+二分区间长度(即答案)+网络流流之啊。
对于每种上下界,牛连源,棚连汇,只有符合区间条件的牛和棚才连边。
网络流判断可行性即可。
(貌似二分+多重匹配是正解?不会多重匹配的蒟蒻飘过。。)

附代码。。。以后真应该把网络流那块写上个
/*
SAP
*/
省得每次写solution report都贴出来。。占字数。。。。我是蒟蒻啊啊啊啊啊啊。。。

#include <iostream>
#include 
<cstdio>
#include 
<cstring>
using namespace std;
#define maxn 1025
#define maxm 90000
#define maxb 22
const int inf = ~0u >> 1;
struct edge
{
    
int p,next,val;
    edge(){}
    edge(
int _p,int _n,int _v):p(_p),next(_n),val(_v){}
}e[maxm];
int flow[maxn],pre[maxn],cnt[maxn],d[maxn],path[maxn],v[maxn],arc[maxn];
int tot,last,n,b;
void init()
{
    last 
= n + b + 1;
    tot 
= 0;
    fill(v,v 
+ last + 1,-1);
    fill(cnt,cnt 
+ last + 1,0);
    fill(d,d 
+ last + 1,0);
    cnt[
0= last + 1;
}
void add(int p,int q,int val)
{
    e[tot] 
= edge(q,v[p],val);
    v[p] 
= tot++;
    e[tot] 
= edge(p,v[q],0);
    v[q] 
= tot++;
}
int mflow()
{
    
int s = 0,t = last;
    
int now,sum,i,k,least,loc;
    
bool flag;
    
for(int i = 0;i <= last;i++)
        arc[i] 
= v[i];
    
for(sum = 0,now = inf,i = s;d[s] < last + 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 = last + 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]])
                
break;
            d[i] 
= least + 1;
            cnt[d[i]]
++;
            arc[i] 
= loc;
            
if(i != s)
            {
                i 
= pre[i];
                now 
= flow[i];
            }
        }
    }
    
return sum;
}
int cow[maxn][maxb];
int barn[maxb];
void graph(int low,int up)
{
    
for(int i = 1;i <= n;i++)
    {
        add(
0,i,1);
        
for(int j = low;j <= up - 1;j++)
            add(i,cow[i][j] 
+ n,1);
    }
    
for(int j = 1;j <= b;j++)
        add(j 
+ n,last,barn[j]);
}
int main()
{
    scanf(
"%d %d",&n,&b);
    
for(int i = 1;i <= n;i++)
        
for(int j = 1;j <= b;j++)
            scanf(
"%d",&cow[i][j]);
    
for(int i = 1;i <= b;i++)
        scanf(
"%d",&barn[i]);
    
int l = 1,r = b,mid;
    
int ans = b;
    
while(l < r)
    {
        mid 
= (l + r) >> 1;
        
bool flag = false;
        
for(int i = 1;i + mid - 1 <= b;i++)
        {
            init();
            graph(i,i 
+ mid);
            
int temp = mflow();
            
//cout << temp << " temp " << i << " i " << i + mid - 1 << " j" << endl;
            if(temp == n)
            {
                flag 
= true;
                
break;
            }
        }
        
if(flag)
        {
            r 
= mid;
            
if(ans > mid)
                ans 
= mid;
        }
        
else
            l 
= mid + 1;
    }
    printf(
"%d\n",ans);
}

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


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


<2011年11月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

导航

统计

常用链接

留言簿(1)

随笔分类(150)

随笔档案(71)

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜