天天看點

SPOJ 1693 網絡流最小割 解題報告

COCONUTS - Coconuts

A group of n castle guards are voting to determine whether African swallows can carry coconuts. While each guard has his own personal opinion on the matter, a guard will often vote contrary to his beliefs in order to avoid disagreeing with the votes of his friends.

You are given a list of guards who either do or do not believe in the coconut-carrying capacity of African swallows, and a list of all pairs of guards who are friends. Your task is to determine how each guard must vote in order to minimize the sum of the total number of disagreements between friends and the total number of guards who must vote against their own beliefs.

Input

The input to this problem will contain multiple test cases. Each test case begins with a single line containing an integer n (where 2 <= n <= 300), the number of guards, and an integer m (where 1 <= m <= n(n-1)/2), the number of pairs of guards who are friends. The second line of the test case contains n integers, where the ith integer is 1 if the ith guard believes in the ability of African swallows to carry coconuts, and 0 otherwise. Finally, the next m lines of the test case each contain two distinct integers i and j (where 1 <= i, j <= n), indicating that guards i and j are friends. Guards within each pair of friends may be listed in any order, but no pair of guards will be repeated. The input is terminated by an invalid test case with n = m = 0, which should not be processed.

Output

For each input test case, print a single line containing the minimum possible sum of the total number of disagreements between all friends plus the total number of guards who must vote against their own beliefs.

Example

Input:

3 3

1 0 0

1 2

1 3

3 2

6 6

1 1 1 0 0 0

1 2

2 3

4 2

3 5

4 5

5 6

0 0

Output:

1

2

[解題報告]

題目大意

N 個城堡守衛正在就非洲的燕子能否搬運椰子而進行投票(他們怎麼這麼無聊 -_-b )。每個人都有自己的看法,但是為了避免跟自己的朋友持相反意見,他們 時常會投相反的票。現在給出每個人的初始看法以及朋友關系,求在某種投票方 案下,違背自己意願的票數與持不同意見的朋友對數的總和最小。(2 <= N <= 300, 1 <= M <= N(N-1)/2)

模組化方法

此題是經典的“二者取其一式問題”。每名守衛 i 作為一個點,若他投贊成票, 則加邊(s, i, 1), (i, t, 0),否則加邊(s, i, 0), (i, t, 1) (設最小割中與源s 連通的點表示 贊同);若i 跟j 是朋友,則加邊(i, j, 1), (j, i, 1)。求一次最小割即為結果。

代碼如下:

#include<cstdio>
#include<cstring> 
#include<string>
#include<algorithm>
#include<map>
#include<queue>  
#include<vector>
using namespace std;  
#define inf 0x3f3f3f3f  
#define maxv 520
#define maxe 520000

int nume=,head[maxv],e[maxe][];

void inline adde(int i,int j,int c)  
{  
    e[nume][]=j;e[nume][]=head[i];head[i]=nume;  
    e[nume++][]=c; 
    e[nume][]=i;e[nume][]=head[j];head[j]=nume;  
    e[nume++][]=;  
}  

int ss,tt,n,m;  
int vis[maxv],lev[maxv]; 

bool bfs()  
{  
    for(int i=;i<maxv;i++)  
    vis[i]=lev[i]=;  
    queue<int>q;  
    q.push(ss);  
    vis[ss]=;  
    while(!q.empty())  
    {  
        int cur=q.front();  
        q.pop();  
        for(int i=head[cur];i!=-;i=e[i][])  
        {  
            int v=e[i][];  
            if(!vis[v]&&e[i][]>)  
            {  
                lev[v]=lev[cur]+;  
                vis[v]=;  
                q.push(v);  
            }  
        }  
    }  
    return vis[tt];  
}  
int dfs(int u,int minf)  
{  
    if(u==tt||minf==) return minf;  
    int sumf=,f;  
    for(int i=head[u];i!=-&&minf;i=e[i][])  
    {  
        int v=e[i][];  
        if(lev[v]==lev[u]+&&e[i][]>)  
        {  
            f=dfs(v,minf<e[i][]?minf:e[i][]);  
            e[i][]-=f;e[i^][]+=f;  
            sumf+=f;minf-=f;  
        }  
    }  
    if(!sumf) lev[u]=-;  
    return sumf;  
}  
int Dinic()  
{  
    int sum=;  
    while(bfs()) sum+=dfs(ss,inf);  
    return sum;  
} 
int main()
{
    while(scanf("%d%d",&n,&m)&&(m+n))
    {
        nume=;
        memset(head,-,sizeof(head));
        ss=,tt=n+;
        for(int i=;i<=n;++i)
        {
            int a;scanf("%d",&a);
            if(a){adde(ss,i,);adde(i,tt,);}
            else {adde(ss,i,);adde(i,tt,);}
        }
        for(int i=;i<=m;++i)
        {
            int u,v;scanf("%d%d",&u,&v);
            adde(u,v,);adde(v,u,);
        }
        printf("%d\n",Dinic());
    }
    return ;
}