BZOJ-2768 [JLOI2010]冠军调查 最小割

题面

题意:每个人可能选0或者1,而且每个人有一些朋友,当他和朋友意见不同的时候,他是可能违背自己的内心而去迎合朋友的,现在问你最好的发言情况下,说谎的人加上意见不同的朋友总数最少,最少是多少

题解:最小割模型

        对于每个人,想选0的,build(s,v,1);想选1的,build(v,t,1);

        因为朋友关系是双向的,build(u,v,1),build(v,u,1);

   因为对于每个人来说 要么割掉这个人 要么割掉这个人和他的朋友的边

        最小割就刚刚好是答案

        因为你割掉的朋友的边就是意见不同的朋友数量 你割掉的连向s或者t的边就是说谎的人

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 350
 4 #define M 100000
 5 const int inf=0x7fffffff/3;
 6 namespace Dinic
 7 {
 8     int head[N],head2[N],p=1;
 9     struct Rec
10     {
11         int go,nex,c;
12     }eg[M*2];
13     void build(int a,int b,int c)
14     {
15         eg[++p]=(Rec){b,head[a],-c};
16         head[a]=p;
17         eg[++p]=(Rec){a,head[b],0};
18         head[b]=p;
19     }
20     int dis[N],Q[N],s[N],S,T,stop,ans;
21     bool bfs()
22     {
23         memset(dis,0,sizeof(dis));
24         dis[T]=1;
25         Q[1]=T;
26         for (int p1=1,p2=1;p1<=p2;p1++)
27         {
28             for (int i=head[Q[p1]];i;i=eg[i].nex)
29                 if (eg[i^1].c<0&&!dis[eg[i].go])
30                 {
31                     dis[eg[i].go]=dis[Q[p1]]+1;
32                     Q[++p2]=eg[i].go;
33                 }
34         }
35         if (!dis[S]) return false;
36         memcpy(head2,head,sizeof(head));
37         return true;
38     }
39     bool dinic(int p,int top)
40     {
41         if (p==T)
42         {
43             int x=inf;
44             for (int i=1;i<=top-1;i++) if (-eg[s[i]].c<x) x=-eg[s[i]].c,stop=i;
45             for (int i=1;i<=top-1;i++) eg[s[i]].c+=x,eg[s[i]^1].c-=x;
46             ans+=x;
47             return true;
48         }
49         for (int &i=head2[p];i;i=eg[i].nex)
50         {
51             if (eg[i].c<0&&dis[eg[i].go]==dis[p]-1)
52             {
53                 s[top]=i;
54                 if (dinic(eg[i].go,top+1)&&top!=stop) return true;
55             }
56         }
57         return false;
58     }
59     int ask()
60     {
61         ans=0;
62         while (bfs()) dinic(S,1);
63         return ans; 
64     }
65     void init(int _S,int _T){
66         S=_S,T=_T;
67     }
68 }
69 using namespace Dinic;
70 void clear()
71 {
72     p=1;
73     memset(head,0,sizeof(head));
74 }
75 int n,m,ss,tt,x,y;
76 int main()
77 {
78     scanf("%d%d",&n,&m);
79     ss=0;tt=n+1;
80     init(ss,tt);
81     for (int i=1;i<=n;i++) 
82     {
83         scanf("%d",&x);
84         if (x) build(ss,i,1);else build(i,tt,1);
85     }
86     for (int i=1;i<=m;i++)
87     {
88         scanf("%d%d",&x,&y);
89         build(x,y,1);
90         build(y,x,1);
91     }
92     printf("%d\n",ask());
93     return 0;
94 }

 

posted @ 2018-09-28 11:07  口香糖万岁  阅读(167)  评论(0编辑  收藏  举报