Typesetting math: 100%

BZOJ1934: [Shoi2007]Vote 善意的投票

BZOJ1934: [Shoi2007]Vote 善意的投票

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

在第一个例子中,所有小朋友都投赞成票就能得到最优解


题解Here!

 

其实没有样例解释更好。。。样例解释把这个题弄鬼畜了。。。
其实应该是都投反对票。。。
这个题显然网络流。
我们可以将两种意见:赞成,反对,设为源汇点S,T
对于每个人x,若投赞成票,连边<S,x,1>;否则连边<x,T,1>
对于每对朋友x,y,我们连边<x,y,1>,<y,x,1>
然后呢?
我们发现我们要割掉最少的边使得S,T在两个对立的集合中。
于是变成了最小割。
直接上板子。。。
附代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#define MAXN 310
#define MAXM 200010
#define MAX 999999999
using namespace std;
int n,m,s,t,c=2;
int head[MAXN],deep[MAXN];
struct Edge{
    int next,to,w;
}a[MAXM];
inline int read(){
    int date=0,w=1;char c=0;
    while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    return date*w;
}
inline void add(int u,int v,int w){
    a[c].to=v;a[c].w=w;a[c].next=head[u];head[u]=c++;
    a[c].to=u;a[c].w=0;a[c].next=head[v];head[v]=c++;
}
bool bfs(){
    int u,v;
    queue<int> q;
    for(int i=1;i<=t;i++)deep[i]=0;
    deep[s]=1;
    q.push(s);
    while(!q.empty()){
        u=q.front();
        q.pop();
        for(int i=head[u];i;i=a[i].next){
            v=a[i].to;
            if(a[i].w&&!deep[v]){
                deep[v]=deep[u]+1;
                if(v==t)return true;
                q.push(v);
            }
        }
    }
    return false;
}
int dfs(int x,int limit){
    if(x==t)return limit;
    int v,sum,cost=0;
    for(int i=head[x];i;i=a[i].next){
        v=a[i].to;
        if(a[i].w&&deep[v]==deep[x]+1){
            sum=dfs(v,min(a[i].w,limit-cost));
            if(sum>0){
                a[i].w-=sum;
                a[i^1].w+=sum;
                cost+=sum;
                if(cost==limit)break;
            }
            else deep[v]=-1;
        }
    }
    return cost;
}
int dinic(){
    int ans=0;
    while(bfs())ans+=dfs(s,MAX);
    return ans;
}
void init(){
    int x,y;
    n=read();m=read();
    s=n+1;t=n+2;
    for(int i=1;i<=n;i++){
        x=read();
        if(x)add(s,i,1);
        else add(i,t,1);
    }
    for(int i=1;i<=m;i++){
        x=read();y=read();
        add(x,y,1);
        add(y,x,1);
    }
}
int main(){
    init();
    printf("%d\n",dinic());
    return 0;
}

 

posted @   符拉迪沃斯托克  阅读(403)  评论(0编辑  收藏  举报
编辑推荐:
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
阅读排行:
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· 软件产品开发中常见的10个问题及处理方法
· Vite CVE-2025-30208 安全漏洞
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· MQ 如何保证数据一致性?
Live2D
欢迎阅读『BZOJ1934: [Shoi2007]Vote 善意的投票』
点击右上角即可分享
微信分享提示