zoukankan      html  css  js  c++  java
  • 圆桌问题(网络流24题)

    题意

    有n个单位,每个单位有一些人,有m张桌子,每张桌子可以坐一些人,每个单位的人不能坐一张桌子,输出方案。

    1<=n<=150, 1<=m<=270。

    题解

    一开始把每个人都看成一个点,然后一个一个依次放进去,就是贪心(可这和网络流有什么关系呢),于是放弃了。去看题解,还真**可以贪心,需要一些排序。

    然后网络流解法来了,把单位和桌子看成两部分,桌子与单位之间连边流量为1就可以保证条件,源点与单位之间连边流量为单位人数,汇点与桌子之间连边流量为桌子容量。

    (我真蠢)

    然后交了一波平常写的网络流结果最后一个点疯狂T,明明前面还都挺快,然后一看讨论很多都是最后一个点T,然后有的说要当前弧优化啥的。

    (不想学)就去看了题解,看到一个dalao说这题不用拆点,弧优化,二分答案,xjb建图,是清流(疑问脸)。一看感觉没啥区别嘛,就只有在dfs里面一句 if(!rest) break;

    结果加上直接原地起飞。

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn=506;
    const int maxm=90006;
    int n,m,tot;
    int cnt=1,s,t,head[maxn];
    struct edge{
      int x,y,val,next;
    }e[maxm];
    
    void add(int x,int y,int val){
      e[++cnt]=(edge){x,y,val,head[x]};
      head[x]=cnt;
    }
    
    int d[maxn];
    
    bool bfs(){
      queue<int> q;
      memset(d,0,sizeof(d));
      q.push(s);d[s]=1;
      while(!q.empty()){
        int x=q.front();
        q.pop();
        for(int i=head[x];i;i=e[i].next){
          int y=e[i].y;
          if(e[i].val&&!d[y]){
            d[y]=d[x]+1;
            if(y==t) return true;
            q.push(y);
          }
        }
      }
      return false;
    }
    
    int dfs(int x,int flow){
      if(x==t) return flow;
      int rest=flow,k;
      for(int i=head[x];i;i=e[i].next){
        int y=e[i].y;
        if(e[i].val&&d[y]==d[x]+1){
          k=dfs(y,min(rest,e[i].val));
          e[i].val-=k;
          e[i^1].val+=k;
          rest-=k;
          if(!rest) break;
        }
      }
      return flow-rest;
    }
    
    int dinic(){
      int res=0;
      while(bfs()) res+=dfs(s,0x3f3f3f);
      return res;
    }
    
    int main(){
      scanf("%d%d",&n,&m);
      s=0;t=n+m+1;
      for(int i=1;i<=n;i++){
        int x;scanf("%d",&x);
        tot+=x;
        add(s,i,x);
        add(i,s,0);
        for(int j=n+1;j<=n+m;j++){
          add(i,j,1);
          add(j,i,0);
        }
      }
      for(int i=n+1;i<=n+m;i++){
        int x;scanf("%d",&x);
        add(i,t,x);
        add(t,i,0);
      }
      int ans=dinic();
      if(ans!=tot){printf("0");return 0;}
      printf("1
    ");
      for(int i=1;i<=n;i++){
        for(int j=head[i];j;j=e[j].next)
         if(!e[j].val) printf("%d ",e[j].y-n);
        putchar(10);
      }
    }
    View Code
  • 相关阅读:
    Visual C++ 2012/2013的内存溢出检測工具
    MATLAB新手教程
    LCD开发之汉字显示
    支持向量机通俗导论(理解SVM的三层境地)
    类与类之间的简单传值
    hibernate官方新手教程 (转载)
    秒杀多线程第四篇 一个经典的多线程同步问题
    Java的位运算符具体解释实例——与(&amp;)、非(~)、或(|)、异或(^)
    mysql基础:mysql与C结合实例
    php实现字符串的排列(交换)(递归考虑所有情况)
  • 原文地址:https://www.cnblogs.com/sto324/p/11353646.html
Copyright © 2011-2022 走看看