【jzyzoj】【p1320 patrol】 巡逻(网络流最小割例题)

  描述 Description

FJ有个农场,其中有n块土地,由m条边连起来。FJ的养牛场在土地1,在土地n有个新开张的雪糕店。Bessie经常偷偷溜到雪糕店,当Bessie去的时候,FJ就要跟上她。但是Bessie很聪明,她在从雪糕店返回时不会经过去雪糕店时经过的农场,因此FJ总是抓不住Bessie。
为了防止Bessie生病,FJ决定把一些诚实的狗放在一些土地(1和n除外)上,使Bessie无法在满足每块土地最多只经过一次的条件的情况下,从养牛场溜到雪糕店然后又溜回养牛场。
求出FJ最少要放多少只狗。数据保证1和n间没有直接的连边。
输入格式 Input Format
* Line 1: Two integers: N and M.

* Lines 2..M+1: Each line contains two integers A and B that describe
    a trail joining fields A and B. It is possible to travel
    along this trail both ways. No trail will appear twice.
输出格式 Output Format
Line 1: A single integer that tells how many fields FJ should guard.
样例输入 Sample Input

6 7
1 2
2 6
1 3
3 4
3 5
4 6
5 6
样例输出 Sample Output

1

OUTPUT DETAILS:

FJ can guard field 2 (for example). FJ could guard both fields 4 and
5, but that would require more dogs.
时间限制 Time Limitation
1s
注释 Hint
数据范围:n<=1000,m<=10000。
来源 Source
usaco

  不得不说这道题细节要求是非常高的,如果不注意就会WA。。。

  刚开始建图也建对了,后来想了想,还是不要用

insert(i,i,1);

这种奇奇怪怪的自身相连来拆点,于是给i,i+n连边。需要注意的是,源点S,T【此题为1,n】,不需要拆。

  1.然后问题就来了,建完图有数据是过不去的。经过思考【看数据】,发现是有坑的。因为你的输出是ans-1,所以如果根本没有路去汇点T,那么ans=0,这时候ans-1为-1............所以输出要特判

  2.第二个坑就是很鬼畜的,,,看如下N=6的对于样例的图【忽略我画的不是双向边】

显然进行拆点后,最大流是2,最小割是1。根据此图建图时,对于给出的x,y相连,显然我们

insert(x+n,y,1);
insert(y+n,x,1);

然而这又是一个坑。如果x=1或者y=1,那么肯定是不需要x+n或y+n的,这里也要特判,才能解决s=1,t=n的答案。

下面是AC代码:

#include<bits/stdc++.h>
#define INF 2100000000
using std::min;
struct qaq
{
    int y,v,nt;
}e[500010];
int rev[50010];
int lin[50050];
int q[50050];
int level[50050];
int s,t;
int len=0;
int n,m;
int ans=0;    

char buf[1<<15],*fs,*ft;
inline char getc(){ return (fs==ft && (ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++; }
int read()
{
    char ch=getc();int x=0;
    while(!isdigit(ch)) ch=getc();
    while(isdigit(ch)) {x=(x<<3)+(x<<1)+ch-‘0‘; ch=getc();}
    return x;
}

void insert(int x,int y,int v)
{
    e[++len].nt=lin[x]; lin[x]=len; e[len].y=y; e[len].v=v; rev[len]=len+1;
    e[++len].nt=lin[y]; lin[y]=len; e[len].y=x; e[len].v=0; rev[len]=len-1;
}

void init()
{
    n=read();m=read();
    s=1;
    t=n;
    for(int i=2;i<n;++i)     insert(i,i+n,1);
    for(int i=1;i<=m;++i)
    {
        int x=read(),y=read();
        if(x>y) std::swap(x,y);
        if(x!=1)
        {
            insert(x+n,y,1);
            insert(y+n,x,1);
        }
        else
        {
            insert(1,y,1);
            insert(y,1,1);
        }
    }
}

bool make_level()
{
    int head=0,tail=1;
    q[1]=s;
    memset(level,-1,sizeof(level));
    level[s]=0;
    while(head++<tail)
    {
        int x=q[head];
        for(int i=lin[x];i;i=e[i].nt)
            if(e[i].v && level[e[i].y]==-1)
            {
                level[e[i].y]=level[x]+1;
                q[++tail]=e[i].y;
            }
    }
    return level[t]>=0;
}

int max_flow(int k,int flow)
{
    if(k==t) return flow;
    int maxflow=0;
    int v;
    for(int i=lin[k];i && (maxflow<flow);i=e[i].nt)
        if(e[i].v && level[e[i].y]==level[k]+1)
            if(v=max_flow(e[i].y,min(e[i].v,flow-maxflow)))
                maxflow+=v,e[i].v-=v,e[rev[i]].v+=v;
    if(!maxflow) level[k]=-1;
    return maxflow;
}

void dinic()
{
    int v;
    while(make_level())
        while(v=max_flow(s,INF))
            ans+=v;
}

int main()
{
//    freopen("a.txt","r",stdin);
    init();
    dinic();
    using std::max;
    if(ans==0) ans=1;
    printf("%d\n",ans-1);
    return 0;
}

时间: 2024-08-06 06:09:51

【jzyzoj】【p1320 patrol】 巡逻(网络流最小割例题)的相关文章

二分图&amp;网络流&amp;最小割等问题的总结

二分图基础: 最大匹配:匈牙利算法 最小点覆盖=最大匹配 最小边覆盖=总节点数-最大匹配 最大独立集=点数-最大匹配 网络流: 带下界网络流 最小割问题的总结: *意义 1.加inf的边表示不能被割,通常用于体现某个点必须属于某个集合 连边(s,u,w)代表如果u不在s割的话需要付出代价w 2.连边(u,v,w)代表如果u在s割,v在t割需要付出代价w 但注意,如果u在t割,v在s割是不需要付出代价的. 那么如果连边(u,v,w)以及(v,u,w)则说明当u与v所属割不同的时候需要付出代价w *

【bzoj3144】[Hnoi2013]切糕 网络流最小割

题目描述 输入 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤P, 1≤y≤Q, 1≤z≤R). 100%的数据满足P,Q,R≤40,0≤D≤R,且给出的所有的不和谐值不超过1000. 输出 仅包含一个整数,表示在合法基础上最小的总不和谐值. 样例输入 2 2 2 1 6 1 6 1 2 6 2 6 样例输出 6 题目大意 给定一个p行q列的矩阵,每个位置可以

HDU 2435 There is a war (网络流-最小割)

There is a war Problem Description There is a sea. There are N islands in the sea. There are some directional bridges connecting these islands. There is a country called Country One located in Island 1. There is another country called Country Another

【bzoj3630】[JLOI2014]镜面通道 对偶图+计算几何+网络流最小割

题目描述 在一个二维平面上,有一个镜面通道,由镜面AC,BD组成,AC,BD长度相等,且都平行于x轴,B位于(0,0).通道中有n个外表面为镜面的光学元件,光学元件α为圆形,光学元件β为矩形(这些元件可以与其他元件和通道有交集,具体看下图).光线可以在AB上任一点以任意角度射入通道,光线不会发生削弱.当出现元件与元件,元件和通道刚好接触的情况视为光线无法透过(比如两圆相切).现在给出通道中所有元件的信息(α元件包括圆心坐标和半径xi,yi,ri,β元件包括左下角和右上角坐标x1,y1,x2,y2

【bzoj2127】happiness 网络流最小割

题目描述 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值.作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的喜悦值总和最大. 输入 第一行两个正整数n,m.接下来是六个矩阵第一个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择文科获得的喜悦值.第二个矩阵为n行m列 此矩阵的第i行

【bzoj2132】圈地计划 网络流最小割

题目描述 最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地.据了解,这块土地是一块矩形的区域,可以纵横划分为N×M块小区域.GDOI要求将这些区域分为商业区和工业区来开发.根据不同的地形环境,每块小区域建造商业区和工业区能取得不同的经济价值.更具体点,对于第i行第j列的区域,建造商业区将得到Aij收益,建造工业区将得到Bij收益.另外不同的区域连在一起可以得到额外的收益,即如果区域(I,j)相邻(相邻

ZOJ3792_Romantic Value(网络流/最小割=最大流/找割边)

解题报告 题目传送门 题意: 给出一个无向图,以及起点与终点.要删除一些边使得起点与终点不连通,在删掉边的权值之和最小的情况下要求删除的边数尽量少. 求出一个比值:剩余边数权值和/删除的边数. 思路: 明显的让起点终点达不到就是一个最小割,用最大流可以求出. 但是求割边边数就不会了,没做过最小割的求割边问题. 割边一定是残留网络中零流的边,但零流不一定是割边. 飞神的想法很奇特.链接传送 可以把残留网络的零流的边设成容量为1,其他设成无穷,再求一次最大流.最后流量一定等于割边边数 另外: 还有一

HDU 4289 Control (网络流-最小割)

Control Problem Description You, the head of Department of Security, recently received a top-secret information that a group of terrorists is planning to transport some WMD 1 from one city (the source) to another one (the destination). You know their

POJ3469_Dual Core CPU(网络流/最小割=最大流/模版)----Dinic模版2.0

解题报告 题目传送门 题意: 双核CPU,n个模块,每个模块必须运行在某个CPU核心上,每个模块在cpu单核的消耗A和B,M对模块要共享数据,如果在同一个核心上不用消耗,否则需要耗费.安排N个模块,使得总耗费最小 思路: 将两个cpu核心看成源点和汇点,其他模块分别与源点汇点连线(表示每个模块可以在任意cpu上运行),m对模块分别连双向边,要使得模块只能在一个cpu上运行,就是找到一个割,源点和汇点必不联通,耗费最少就是最小割,最小割最大流原理转换成求最大流. 这题数据大,没优化TLE了,加了两