网络流合集:bzoj1433,1934,1854 题解

转载请注明:http://blog.csdn.net/jiangshibiao/article/details/23992205

网络流/二分图大合集

【NO.1*原题】

1433: [ZJOI2009]假期的宿舍

Time Limit: 10 Sec  Memory Limit: 162 MB

Submit: 972  Solved: 422

[Submit][Status]

Description

Input

Output

Sample Input

1

3

1 1 0

0 1 0

0 1 1

1 0 0

1 0 0

Sample Output

? ?

HINT

对于30% 的数据满足1 ≤ n ≤ 12。

对于100% 的数据满足1 ≤ n ≤ 50,1 ≤ T ≤ 20。

【NO.1*分析】想了非常长时间。igzhou大神非要我用二分图写,但我就是要转化成网络流。首先我们把住校的人(也就是有床的人)的床和汇点T连边。注意这是”床“。而不是人本身。

然后把源点S和全部人连一条边。

再把互相认识的人中人和床连边。

比方1是住校的,2是走读的。2认识1,就把2和1的床连边。

注意不是2和1连边。

自然,对于住校生。自己和自己的床也要连边。

以上全部边的容量都是1。

坑点:输出不用回车。

【NO.1*代码】

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 305
#define INF 2000000000
using namespace std;
int map[N][N],f[N],q[N],num[N],x,test,ans,n,m,i,j,cnt;
bool bfs()
{
  memset(f,-1,sizeof(f));
  int h=0,t=1;q[1]=0;f[0]=1;
  while (h<t)
  {
    int now=q[++h];if (now==n) return 1;
    for (int i=0;i<=n;i++)
      if (map[now][i]&&f[i]==-1)
      {
        f[i]=f[now]+1;q[++t]=i;
      }
  }
  return 0;
}
int dinic(int sta,int sum)
{
  if (sta==n) return sum;
  int os=sum;
  for (int i=0;(i<=n)&&os;i++)
    if (map[sta][i]&&f[i]==f[sta]+1)
    {
      int Min=dinic(i,min(map[sta][i],os));
      map[sta][i]-=Min;map[i][sta]+=Min;os-=Min;
    }
  if (os==sum) f[sta]=-1;
  return sum-os;
}
int main()
{
  scanf("%d",&test);
  while (test)
  {
    test--;memset(map,0,sizeof(map));
    scanf("%d",&n);cnt=0;
    for (i=1;i<=n;i++)
    {
      scanf("%d",&num[i]);
      if (num[i]) map[i+n][2*n+1]=1;
    }
    for (i=1;i<=n;i++)
    {
      scanf("%d",&x);
      if (!num[i]||num[i]&&!x) map[0][i]=1,cnt++;
    }
    for (i=1;i<=n;i++)
      for (j=1;j<=n;j++)
      {
        scanf("%d",&x);
        if (x||i==j) map[i][j+n]=1;
      }
    n=2*n+1;ans=0;
    while (bfs()) ans+=dinic(0,INF);
    if (ans==cnt) puts("^_^");else puts("T_T");
  }
  return 0;
}

【NO.2*原题】

1934: [Shoi2007]Vote 善意的投票

Time Limit: 1 Sec  Memory Limit: 64 MB

Submit: 897  Solved: 537

[Submit][Status]

Description

幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉。对他们来说。这个问题并非非常重要。于是他们决定发扬谦让精神。尽管每一个人都有自己的主见,可是为了照应一下自己朋友的想法,他们也能够投和自己本来意愿相反的票。

我们定义一次投票的冲突数为好朋友之间发生冲突的总数加上和全部和自己本来意愿发生冲突的人数。 我们的问题就是,每位小朋友应该如何投票,才干使冲突数最小?

Input

第一行仅仅有两个整数n,m,保证有2≤n≤300,1≤m≤n(n-1)/2。当中n代表总人数。m代表好朋友的对数。文件第二行有n个整数,第i个整数代表第i个小朋友的意愿,当它为1时表示允许睡觉,当它为0时表示反对睡觉。

接下来文件还有m行,每行有两个整数i,j。

表示i,j是一对好朋友,我们保证不论什么两对i,j不会反复。

Output

仅仅须要输出一个整数,就可以能的最小冲突数。

Sample Input

3 3

1 0 0

1 2

1 3

3 2

Sample Output

1

HINT

在第一个样例中,全部小朋友都投赞成票就能得到最优解

Source

Day2

【NO.2*分析】我感觉这个的建图有点诡异。把全部1的小朋友和S连,否则和T连。再朋友间互相连。求最大流。

【NO.2*代码】

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 302
#define INF 2000000000
using namespace std;
int map[N][N],f[N],q[N],num,x,y,ans,n,m,i;
bool bfs()
{
  memset(f,-1,sizeof(f));
  int h=0,t=1;q[1]=0;f[0]=1;
  while (h<t)
  {
    int now=q[++h];if (now==n) return 1;
    for (int i=0;i<=n;i++)
      if (map[now][i]&&f[i]==-1)
      {
        f[i]=f[now]+1;
        q[++t]=i;
      }
  }
  return 0;
}
int dinic(int sta,int sum)
{
  if (sta==n) return sum;int os=sum;
  for (int i=0;(i<=n)&&os;i++)
    if (map[sta][i]&&f[i]==f[sta]+1)
    {
      int Min=dinic(i,min(map[sta][i],os));
      map[sta][i]-=Min;map[i][sta]+=Min;os-=Min;
    }
  if (os==sum) f[sta]=-1;return sum-os;
}
int main()
{
  scanf("%d%d",&n,&m);
  for (i=1;i<=n;i++)
  {
    scanf("%d",&num);if (num) map[0][i]=1;else map[i][n+1]=1;
  }
  for (i=1;i<=m;i++)
  {
    scanf("%d%d",&x,&y);map[x][y]=map[y][x]=1;
  }
  n++;while (bfs()) ans+=dinic(0,INF);
  printf("%d",ans);
  return 0;
}

【NO.3*原题】

1854: [Scoi2010]游戏

Time Limit: 5 Sec  Memory Limit: 162 MB

Submit: 1954  Solved: 689

[Submit][Status]

Description

lxhgww近期迷上了一款游戏。在游戏里。他拥有非常多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示。当他使用某种装备时。他仅仅能使用该装备的某一个属性。而且每种装备最多仅仅能使用一次。 游戏进行到最后。lxhgww遇到了终极boss,这个终极boss非常奇怪。攻击他的装备所使用的属性值必须从1開始连续递增地攻击,才干对boss产生伤害。

也就是说一開始的时候,lxhgww仅仅能使用某个属性值为1的装备攻击boss,然后仅仅能使用某个属性值为2的装备攻击boss,然后仅仅能使用某个属性值为3的装备攻击boss……以此类推。
如今lxhgww想知道他最多能连续攻击boss多少次?

Input

输入的第一行是一个整数N,表示lxhgww拥有N种装备 接下来N行,是对这N种装备的描写叙述,每行2个数字,表示第i种装备的2个属性值

Output

输出一行。包含1个数字,表示lxhgww最多能连续攻击的次数。

Sample Input

3

1 2

3 2

4 5

Sample Output

2

HINT

【数据范围】

对于30%的数据。保证N < =1000

对于100%的数据,保证N < =1000000

Source

Day1

【NO.3*分析】这个构图是挺经典的。最后我是用二分图A的。

事实上这也挺好理解。左側是各种属性,右側是各种装备。对于每个装备,连两个属性。

这样就能保证选了一个后,对于同一个装备的还有一个属性,就不会选了。

【NO.3*代码】

#include<cstdio>
#include<cstring>
using namespace std;
struct arr{int go,next;}a[2000005];
int belong[1000005],end[10005];
int visit[1000005];
int x,y,n,i,cnt;
char ch;
void add(int x,int y)
{
  a[++cnt].go=y;a[cnt].next=end[x];end[x]=cnt;
}
inline int Read()
{
  while (ch<‘0‘||ch>‘9‘) ch=getchar();
  int s=0;while (ch>=‘0‘&&ch<=‘9‘) s=s*10+ch-48,ch=getchar();return s;
}
bool find(int k)
{
  for (int i=end[k];i;i=a[i].next)
  {
    int go=a[i].go;
    if (visit[go]==i) continue;
    visit[go]=i;
    if (!belong[go]||find(belong[go]))
    {
      belong[go]=k;
      return true;
    }
  }
  return false;
}
int main()
{
  scanf("%d",&n);ch=‘ ‘;
  for (i=1;i<=n;i++)
  {
    x=Read();y=Read();
    add(x,i);add(y,i);
  }
  memset(belong,0,sizeof(belong));
  for (i=1;i<=10000;i++)
    if (!find(i)) break;
  i--;printf("%d",i);/
  return 0;
}
时间: 2024-07-29 16:15:27

网络流合集:bzoj1433,1934,1854 题解的相关文章

NOIP提高组 1999 &amp; 2000 题解合集

[序言]话说我在学神奇算法的时候,基础应该也要巩固,于是打算提前把NOIP提高组的刷完. 具体的题目描述和提交我就在VIJOS上完成. [1999.1] 描述 给定一个信封,最多只允许粘贴N张邮票,计算在给定M(N+M<=10)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大max ,使得1-max之间的每一个邮资值都能得到. 例如,N=3,M=2,如果面值分别为1分.4分,则在l分-6分之间的每一个邮资值都能得到(当然还有8分.9分和12分):如果面值分别为1分.3分

[题解+总结]动态规划大合集II

1.前言 大合集总共14道题,出自江哥之手(这就没什么好戏了),做得让人花枝乱颤.虽说大部分是NOIP难度,也有简单的几道题目,但是还是做的很辛苦,有几道题几乎没思路,下面一道道边看边分析一下. 2.lis 最长上升子序列 唯一一道裸题,但是O(n^2)过不了,临时看了看O(n log n)的二分做法和线段树做法.先来讲讲简单的二分做法,其本质就是在O(n^2)上进行优化,需要证明一个结论.设当前处理数列第k位,存在: (1)a[i]<a[j]<a[k]: (2)i<j<k: (3

【分享】数学物理方法/方程学习资源合集下载

 二阶椭圆型方程与椭圆型方程组.pdf 3.1 MB  弹性结构的数学理论.pdf 4.2 MB  物理学中的数学方法 第一卷_拜仑.pdf 5.2 MB  物理学中的数学方法 第二卷_拜仑.pdf 5.9 MB  中国科学院研究生教学丛书 数学物理中的渐进方法.pdf 7.4 MB  数学物理方法1(柯朗)(英文版).pdf 5.2 MB  数学物理方法2(柯朗)(英文版).pdf 8.3 MB  数学物理方程与特殊函数(王元明)课后答案.pdf 10.38 MB  数学物理方程与特殊函数-王

几何入门合集

F. Mirror 题意 链接 三维几何镜像问题: 有n个人在y=0的平面上(及xoz平面).z=0平面上有一面镜子(边平行于坐标轴).z=a平面上有q个点(保证a大于所有人的z坐标). 所有人面朝镜子,且在镜子和q个点之间(即每个人的z坐标保证0<z<a). 问对于某个点,让所有人能够通过镜子看到那个点的镜子的最小面积. 题解 首先考虑镜面,我们可以通过(初中科学的)镜面反射原理,关于z=0做出z=a的对称平面z=-a.问题就变成了n个人看z=-a上的某个点.(下图绿点是人,红点是询问点)

Vim命令合集

来源:Vim命令合集 命令历史 以:和/开头的命令都有历史纪录,可以首先键入:或/然后按上下箭头来选择某个历史命令. 启动vim 在命令行窗口中输入以下命令即可 vim 直接启动vim vim filename 打开vim并创建名为filename的文件 文件命令 打开单个文件 vim file 同时打开多个文件 vim file1 file2 file3 ... 在vim窗口中打开一个新文件 :open file 在新窗口中打开文件 :split file 切换到下一个文件 :bn 切换到上一

[转载]VIM命令合集

Vim命令合集 http://www.cnblogs.com/softwaretesting/archive/2011/07/12/2104435.html 命令历史 以:和/开头的命令都有历史纪录,可以首先键入:或/然后按上下箭头来选择某个历史命令. 启动vim 在命令行窗口中输入以下命令即可 vim 直接启动vim vim filename 打开vim并创建名为filename的文件 文件命令 打开单个文件 vim file 同时打开多个文件 vim file1 file2 file3 ..

前端资源教程合集

综合类 前端知识体系 前端知识结构 Web前端开发大系概览 Web前端开发大系概览-中文版 Web Front-end Stack v2.2 En类资源汇总 免费的编程中文书籍索引 前端书籍 前端免费书籍大全 前端知识体系 免费的编程中文书籍索引 智能社 - 精通JavaScript开发 重新介绍 JavaScript(JS 教程) 麻省理工学院公开课:计算机科学及编程导论 JavaScript中的this陷阱的最全收集--没有之一 JS函数式编程指南 JavaScript Promise迷你书

减肥视频合集

薄荷味视频合集 http://www.boohee.com/posts/view/222199/1?sub_id=3 我最爱练习Insanity http://www.bilibili.com/video/av3596373/

转载:2013计算机视觉代码合集

转载,原文地址http://blog.csdn.net/daoqinglin/article/details/23607079 -------------------------------------------------------------------------- 来源: http://www.yuanyong.org/cv/cv-code-one.html http://www.yuanyong.org/cv/cv-code-two.html http://www.yuanyong