bzoj1934&bzoj2768:最小割

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1934&bzoj2768:最小割相关的知识,希望对你有一定的参考价值。

果然智商是硬伤。。。去掉最少的边使图不联通,不联通意味着不会还存在朋友之间有矛盾,那么去掉的边有两种可能,1是与st相连的(Orz就是这里忽略了),那么就是违心说话的人,另外就是中间的边,那么就是朋友之间立场不同的人。然后跑一下最大流就好了。

-------------------------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
const int inf=0x3f3f3f3f;
int read(){
    int x=0;char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)){
        x=x*10+c-0;
        c=getchar();
    }
    return x;
}
struct edge{
    int to,cap;
    edge *next,*rev;
};
edge e[200000],*pt=e,*head[305],*cur[305],*p[305];
int d[305],cnt[305];
void add(int u,int v,int d){
    pt->to=v;pt->cap=d;pt->next=head[u];head[u]=pt++;
}
void adde(int u,int v,int d){
    add(u,v,d);add(v,u,0);
    head[u]->rev=head[v];
    head[v]->rev=head[u];
}
int maxflow(int s,int t,int n){
    clr(d,0);clr(cnt,0);cnt[0]=n;
    int flow=0,a=inf,x=s;
    while(d[s]<n){
        edge *ee;
        for(ee=cur[x];ee;ee=ee->next){
            if(ee->cap>0&&d[ee->to]+1==d[x]) break;
        }
        if(ee){
            p[ee->to]=cur[x]=ee;
            a=min(a,ee->cap);
            x=ee->to;
            if(x==t){
                while(x!=s){
                    p[x]->cap-=a;
                    p[x]->rev->cap+=a;
                    x=p[x]->rev->to;
                }
                flow+=a;
                a=inf;
            }
        }else{
            if(!--cnt[d[x]] ) break;
            d[x]=n;
            for(ee=head[x];ee;ee=ee->next)
              if(ee->cap>0&&d[ee->to]+1<d[x]){
                  d[x]=d[ee->to]+1;
                  cur[x]=ee;
              }
            cnt[d[x]]++;
            if(x!=s) x=p[x]->rev->to;
        }
    }
    return flow;
}
int main(){
    int n=read(),m=read(),s=0,t=n+1,tot=t+1,tmp;
    rep(i,n){
        if(tmp=read()) adde(s,i,1);
        else adde(i,t,1);
    }
    rep(i,m){
        int u=read(),v=read();
        adde(u,v,1);adde(v,u,1);
    }
    printf("%d\\n",maxflow(s,t,tot));
    return 0;
}

-------------------------------------------------------------------------------------------

2768: [JLOI2010]冠军调查

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 857  Solved: 579
[Submit][Status][Discuss]

Description

一年一度的欧洲足球冠军联赛已经进入了淘汰赛阶段。随着卫冕冠军巴萨罗那的淘汰,英超劲旅切尔西成为了头号热门。新浪体育最近在吉林教育学院进行了一次大规模的调查,调查的内容就是关于切尔西能否在今年问鼎欧洲冠军。新浪体育的记者从各个院系中一共抽取了n位同学作为参与者,大家齐聚一堂,各抒己见。每一位参与者都将发言,阐述自己的看法。参与者的心里都有一个看法,比如FireDancer认为切尔西不可能夺冠,而WaterDancer认为切尔西一定问鼎。但是因为WaterDancer是FireDancer的好朋友,所以可能FireDancer为了迁就自己的好朋友,会在发言中支持切尔西。也就是说每个参与者发言时阐述的看法不一定就是心里所想的。现在告诉你大家心里的想法和参与者的朋友网,希望你能安排每个人的发言内容,使得违心说话的人的总数与发言时立场不同的朋友(对)的总数的和最小。
 

Input

第一行两个整数n和m,其中n(2≤n≤300)表示参与者的总数,m(0≤m≤n(n-1)/2)表示朋友的总对数。
第二行n个整数,要么是0要么是1。如果第i个整数的值是0的话,表示第i个人心里认为切尔西将与冠军无缘,如果是1的话,表示他心里认为切尔西必将夺魁。
下面m行每行两个不同的整数,i和j(1≤i, j≤n)表示i和j是朋友。注意没有一对朋友会在输入中重复出现。朋友关系是双向的,并且不会传递。
 

Output

 
只有一个整数,为最小的和。

Sample Input

3 3
1 0 0
1 2
1 3
2 3

Sample Output

1

HINT

最好的安排是所有人都在发言时说切尔西不会夺冠。这样没有一对朋友的立场相左,只有第1个人他违心说了话。

Source

 
[Submit][Status][Discuss]

以上是关于bzoj1934&bzoj2768:最小割的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1934:[SHOI2007]善意的投票 & BZOJ2768:[JLOI2010]冠军调查——题解

BZOJ 1934--善意的投票(最小割)

BZOJ 1934 善意的投票(最小割)

bzoj 1934 : [Shoi2007]Vote 善意的投票 最小割

BZOJ 1934 [Shoi2007]Vote 善意的投票(最小割)

BZOJ-1934: [Shoi2007]Vote 善意的投票 (网络流最小割)