BZOJ1934Vote 善意的投票

1934: [Shoi2007]Vote 善意的投票
Time Limit: 1 Sec Memory Limit: 64 MB
Submit: 1574 Solved: 960
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
在第一个例子中,所有小朋友都投赞成票就能得到最优解
Source
Day2
最小割模型。。
网络流最大流+超级源超级汇。。
本来建图的时候f[0][i]=1等等都写成了f[0][x]=1。。坑爹啊。。查了一节课没看出来。。果然我太弱

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int f[601][601],head,tail,dis[601],ans,sum=0,n,m,i,q[601];

int read()
{
    int s=0,w=1;
    char ch=getchar();
    while (ch<'0' || ch>'9')
      {
        if (ch=='-')
          w=-1;
        ch=getchar();
      }
    while (ch>='0' && ch<='9')
      {
        s=s*10+ch-'0';
        ch=getchar();
      }
    return s*w;
}

int bfs()
{
    int j,p;
    memset(dis,-1,sizeof(dis));
    dis[0]=0;
    head=0;
    tail=1;
    q[0]=0;
    while (head<tail)
      {
        head++;
        p=q[head];
        for (j=1;j<=n+1;j++)
          if (dis[j]<0 && f[p][j]>0)
            {
              dis[j]=dis[p]+1;
              tail++;
              q[tail]=j;
            }
      }
    if (dis[n+1]!=-1)
      return 1;
    else
      return 0;
}

int dfs(int s,int low)
{
    int j,a=0;
    if (s==n+1)
      return low;
    for (j=1;j<=n+1;j++)
      if (f[s][j]>0 && dis[j]==dis[s]+1 && (a=dfs(j,min(low,f[s][j]))))
        {
            f[s][j]-=a;
            f[j][s]+=a;
            return a;
        }
    return 0;
}

int main()
{
    int x,y;
    n=read();
    m=read();
    memset(f,0,sizeof(f));
    for (i=1;i<=n;i++)
      {
        x=read();
        if (x)
          {
            f[0][i]=1;
            f[i][0]=0;
          }
        else
          {
            f[i][n+1]=1;
            f[n+1][i]=0;
          }
      }
    for (i=1;i<=m;i++)
      {
        x=read();
        y=read();
        f[x][y]=1;
        f[y][x]=1;
      }
    ans=0;
    while (bfs())
      while (sum=dfs(0,0x7fffffff))
        ans+=sum;
    printf("%d",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值