• 1934. [SHOI2007]善意的投票【最小割】


    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

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

    好久没做网络流了有点手生(其实还是因为菜
    第一眼二分图最小割
    第二眼emmm……
    很容易想到同一阵营的分一边然后求最小割,
    可是一个人改变主意的话和他的老铁们就冲突了咋整?
    那么就同一阵营朋友间连双向边。
    为什么是双向边呢?我觉得一篇题解写的非常清楚:
    "若两个人有冲突,则只需要其中任意一个人改变意见就行了
     简单说是让a同意b的意见或者b同意a的意见,
     所以只需割掉一条边满足一种情况就可以了,
     但是有两种情况,所以建双向边"

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<queue>
     6 #define MAXM (1000000+10)
     7 #define MAXN (30000+10)
     8 using namespace std;
     9 struct node
    10 {
    11     int Flow;
    12     int next;
    13     int to;
    14 }edge[MAXM*2];
    15 int Depth[MAXN];
    16 int head[MAXN],num_edge;
    17 int n,m,s,e,x,y,INF,a[MAXN];
    18 queue<int>q;
    19 
    20 void add(int u,int v,int l)
    21 {
    22     edge[++num_edge].to=v;
    23     edge[num_edge].Flow=l;
    24     edge[num_edge].next=head[u];
    25     head[u]=num_edge;
    26 }
    27 
    28 bool Bfs(int s,int e)
    29 {
    30     memset(Depth,0,sizeof(Depth));
    31     q.push(s);
    32     Depth[s]=1;
    33     while (!q.empty())
    34     {
    35         int x=q.front(); q.pop();
    36         for (int i=head[x];i!=0;i=edge[i].next)
    37             if (!Depth[edge[i].to] && edge[i].Flow>0)
    38             {
    39                 Depth[edge[i].to]=Depth[x]+1;
    40                 q.push(edge[i].to);
    41             }
    42     }
    43     return Depth[e];
    44 }
    45 
    46 int Dfs(int x,int low)
    47 {
    48     int Min,f=0;
    49     if (x==e || low==0)
    50         return low;
    51     for (int i=head[x];i!=0;i=edge[i].next)
    52         if (edge[i].Flow>0 && Depth[edge[i].to]==Depth[x]+1 && (Min=Dfs(edge[i].to,min(low,edge[i].Flow))))
    53         {
    54             edge[i].Flow-=Min;
    55             edge[((i-1)^1)+1].Flow+=Min;
    56             low-=Min;
    57             f+=Min;
    58             if (low==0) return f;
    59         }
    60     if (!f) Depth[x]=-1;
    61     return f;
    62 }
    63 
    64 int Dinic(int s,int e)
    65 {
    66     int Ans=0;
    67     while (Bfs(s,e))
    68         Ans+=Dfs(s,0x7fffffff);
    69     return Ans;
    70 }
    71 
    72 int main()
    73 {
    74     memset(&INF,0x7f,sizeof(INF));
    75     scanf("%d%d",&n,&m);
    76     s=0,e=20001;
    77     for (int i=1;i<=n;++i)
    78     {
    79         scanf("%d",&a[i]);
    80         if (a[i]==1)  add(0,i,1),add(i,0,0);
    81         else  add(i,e,1); add(e,i,0);
    82     }
    83     for (int i=1;i<=m;++i)
    84     {
    85         scanf("%d%d",&x,&y);
    86         if (a[x]==a[y])
    87         {
    88             add(x,y,1); add(y,x,0);
    89             add(x,y,0); add(y,x,1);
    90         }
    91         else
    92         {
    93             if (a[x]==0) swap(x,y);
    94             add(x,y,1); add(y,x,0);
    95          }
    96     }
    97     printf("%d",Dinic(s,e));
    98 }
  • 相关阅读:
    JDBC原理及常见错误分析
    response,session,cookie
    Activity LifeCycle (安卓应用的运行机制)
    简单的接口取数据渲染到图表
    图表里面双重下拉框进行判断
    用js方式取得接口里面json数据的key和value值
    一个div多个图表共用一个图例
    一个页面多图表展示(四个div的方式)
    vue组件之子组件和父组件
    根据判断对颜色进行改变
  • 原文地址:https://www.cnblogs.com/refun/p/8682183.html
Copyright © 2020-2023  润新知