BZOJ-1934: [Shoi2007]Vote 善意的投票 题解(最大流)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1934

思路:对于一个小朋友支持,将其与源s相连,否则与汇t相连,好朋友之间相连,容量均为1。

对于一个割C(S,T),若某一支持的小朋友被划到T,那么他与s之间的连边必定被割去,且与同在T的好用的边可以不属于割边,若在S,则他与划在T的好友的边必为割边,所以每个割都对应着一种冲突情况且等于冲突数,所以最小割即为答案。

代码:

#include 

#include 

#include 

 

using namespace std;

 

#define MAXN 305

 

struct node {

    int t,f;

    node *next,*pair;

};

 

node *head[MAXN],*d[MAXN];

 

int gap[MAXN],h[MAXN];

 

int n,m;

int S,T;

 

void INSERT(int s,int t,int f){

    node *p=new(node);

    p->t=t;;

    p->f=f;

    p->next=head[s];

    head[s]=p;

}

 

int ans=0;

 

int sap(int v,int flow){

    if (v==T) return flow;

    int rec=0;

    for (node *p=d[v];p;p=p->next){

        if (p->f&&h[v]==h[p->t]+1){

            int ret=sap(p->t,min(flow-rec,p->f));

            p->f-=ret;

            p->pair->f+=ret;

            d[v]=p;

            if ((rec+=ret)==flow) return flow;

        }

    }

    if (!(--gap[h[v]])) h[S]=T;

    gap[++h[v]]++;

    d[v]=head[v];

    return rec;

}

 

int main(){

    memset(head,0,sizeof(head));

    scanf("%d%d",&n,&m);

    S=n+1;

    T=S+1;

    for (int i=0;i++pair=head[i];

            head[i]->pair=head[S];

        } else {

            INSERT(i,T,1);

            INSERT(T,i,0);

            head[i]->pair=head[T];

            head[T]->pair=head[i];

        }

    }

    while (m--){

        int s,t;

        scanf("%d%d",&s,&t);

        INSERT(s,t,1);

        INSERT(t,s,1);

        head[s]->pair=head[t];

        head[t]->pair=head[s];

    }

    memset(gap,0,sizeof(gap));

    memset(h,0,sizeof(h));

    for (int i=0;i++

你可能感兴趣的:(BZOJ-1934: [Shoi2007]Vote 善意的投票 题解(最大流))