poj2914(無向圖最小割)

題目鏈接:http://poj.org/problem?id=2914

思路:模板題,複雜度是n的三次方

#pragma GCC optimize(2)
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inff = 0x3f3f3f3f3f3f3f3f;
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
#define REW(a,b) memset(a,b,sizeof(a))
#define inf int(0x3f3f3f3f)
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define ss(a) scanf("%s",a)
#define mod ll(1000)
#define pb push_back
#define eps 1e-8
#define lc d<<1
#define rc d<<1|1
#define Pll pair<ll,ll>
#define P pair<int,int>
#define pi acos(-1)
int n,m;
int stoer_wagner(int n,int m)
{
    const int N=508;
    int G[N][N],visited[N],v[N],w[N],min_cut=inf;
    REW(G,0);int x,y,z;
    for(int i=0;i<m;i++)
    {
        if(i<n) v[i]=i;
        si(x),si(y),si(z);
        //int x=a[i+1].v-1,y=a[i+1].u-1;
        G[x][y]+=z;
        G[y][x]+=z;
    }
    while(n>1)
    {
        int pre=0;
        memset(visited,0,sizeof(visited));
        memset(w,0,sizeof(w));
        for(int i=1;i<n;++i)
        {
            int k=-1;
            for(int j=1;j<n;++j)  //	選取V-A中的w(A,x)最大的點x加入集合
            {
                if(!visited[v[j]])
                {
                    w[v[j]]+=G[v[pre]][v[j]];
                    if(k==-1||w[v[k]]<w[v[j]]) k = j;
                }
            }
            visited[v[k]] = true;		//	標記該點x已經加入A集合
            if(i==n-1)				//	若|A|=|V|(所有點都加入了A),結束
            {
                const int s=v[pre],t=v[k];		//	令倒數第二個加入A的點(v[pre])爲s,最後一個加入A的點(v[k])爲t
                min_cut = min(min_cut, w[t]);		//	則s-t最小割爲w(A,t),用其更新min_cut
                for(int j=0;j<n;++j)			//	Contract(s, t)
                {
                    G[s][v[j]]+=G[v[j]][t];
                    G[v[j]][s]+=G[v[j]][t];
                }
                v[k]=v[--n];						//	刪除最後一個點(即刪除t,也即將t合併到s)
            }
            // else 繼續
            pre = k;
        }
    }
    return min_cut;
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    while(cin>>n>>m)
    {
        //int zz=stoer_wagner(n,m);
        cout<<stoer_wagner(n,m)<<endl;
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章