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

https://www.lydsy.com/JudgeOnline/problem.php?id=1934

https://www.lydsy.com/JudgeOnline/problem.php?id=2768

幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉。对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神。虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票。我们定义一次投票的冲突数为好朋友之间发生冲突的总数加上和所有和自己本来意愿发生冲突的人数。 我们的问题就是,每位小朋友应该怎样投票,才能使冲突数最小?

最小割模型,S表示睡午觉,T表示不睡,然后连就行了。

然后这道简单题竟然出现在了两个省选题里面……

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=350;
const int M=N*N+N;
const int INF=1e9;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
struct node{
    int nxt,to,w;
}edge[M];
int head[N],cnt=-1,S,T;
void add(int u,int v,int w){
    edge[++cnt].to=v;edge[cnt].w=w;edge[cnt].nxt=head[u];head[u]=cnt;
}
int lev[N],cur[N],dui[N];
bool bfs(int m){
    int r=0;
    for(int i=1;i<=m;i++){
    lev[i]=-1;
    cur[i]=head[i];
    }
    dui[0]=S,lev[S]=0;
    int u,v;
    for(int l=0;l<=r;l++){
    u=dui[l];
    for(int e=head[u];e!=-1;e=edge[e].nxt){
        v=edge[e].to;
        if(edge[e].w>0&&lev[v]==-1){ 
        lev[v]=lev[u]+1;
        r++;
        dui[r]=v; 
        if(v==T)return 1; 
        }
    }
    }
    return 0;
}
int dinic(int u,int flow,int m){
    if(u==m)return flow;
    int res=0,delta;
    for(int &e=cur[u];e!=-1;e=edge[e].nxt){
    int v=edge[e].to;
    if(edge[e].w>0&&lev[u]<lev[v]){ 
        delta=dinic(v,min(edge[e].w,flow-res),m); 
        if(delta>0){
        edge[e].w-=delta;
        edge[e^1].w+=delta;
        res+=delta;
        if(res==flow)break; 
        }
    }
    }
    if(res!=flow)lev[u]=-1;
    return res;
}
int c[N];
int main(){
    memset(head,-1,sizeof(head));
    int n=read(),m=read();
    S=n+1,T=S+1;
    for(int i=1;i<=n;i++){
    if(c[i]=read())add(S,i,1),add(i,S,0);
    else add(i,T,1),add(T,i,0);
    }
    for(int i=1;i<=m;i++){
    int a=read(),b=read();
    if(c[b])swap(a,b);
    add(a,b,1),add(b,a,0);
    }
    int ans=0;
    while(bfs(T))ans+=dinic(S,INF,T);
    printf("%d\n",ans);
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +

+++++++++++++++++++++++++++++++++++++++++++

posted @ 2018-05-19 15:34  luyouqi233  阅读(204)  评论(0编辑  收藏  举报