[hdu6081]度度熊的王国战略

Time Limit: 40000/20000 MS (Java/Others)
Memory Limit: 32768/132768 K (Java/Others)

Problem Description
度度熊国王率领着喵哈哈族的勇士,准备进攻哗啦啦族。
哗啦啦族是一个强悍的民族,里面有充满智慧的谋士,拥有无穷力量的战士。
所以这一场战争,将会十分艰难。
为了更好的进攻哗啦啦族,度度熊决定首先应该从内部瓦解哗啦啦族。
第一步就是应该使得哗啦啦族内部不能同心齐力,需要内部有间隙。
哗啦啦族一共有 n n 个将领,他们一共有 m m 个强关系,摧毁每一个强关系都需要一定的代价。
现在度度熊命令你需要摧毁一些强关系,使得内部的将领,不能通过这些强关系,连成一个完整的连通块,以保证战争的顺利进行。
请问最少应该付出多少的代价。

Input
本题包含若干组测试数据。
第一行两个整数 n m n,m ,表示有 n n 个将领, m m 个关系。
接下来 m m 行,每行三个整数 u , v , w u,v,w 。表示u将领和v将领之间存在一个强关系,摧毁这个强关系需要代价 w w

数据范围:
2 < = n < = 3000 2<=n<=3000
1 < = m < = 100000 1<=m<=100000
1 < = u , v < = n 1<=u,v<=n
1 < = w < = 1000 1<=w<=1000

Output
对于每组测试数据,输出最小需要的代价。

Sample Input

2 1
1 2 1
3 3
1 2 5
1 2 4
2 3 3

Sample Output

1
3

题解:
全局最小割裸题

全局最小割的实现:
1.先选出G中的某对点s-t的最小割,更新一下答案。
2.将选出的s-t合并到一个集合中。
3.反复这么做,直到G只剩下一个顶点。

如何找到当前状态下的最小割?
1.先随便选一个起点(或合并之后的集合)。
2.以这个起点开始,遍历所有与这个点(集合)相邻的其他点(集合)
3.用大根堆存储被连接的集合,最后直接把最后加入剩下的那个点和最后拓展的那个点union到一个集合里面就行。

#include<bits/stdc++.h>
#define ll long long
#define pa pair<ll,int>
using namespace std;
const ll INF=1e18;
struct edge{
    int to,w;
};
int n,m;
vector<edge>G[3004];
int f[3004],lk[3004];
int Find(int x){return f[x]==x?x:f[x]=Find(f[x]);}
void Union(int x,int y){
    int p=x;
    while(lk[p])p=lk[p];
    lk[p]=y;
    f[y]=x;
}
ll val[3004];
bool vis[3004];
priority_queue<pa>q;
ll msp(int cnt,int &s,int &t){
    for(int i=1;i<=n;i++){
        vis[i]=0;
        val[i]=0;
    }
    while(!q.empty())q.pop();
    t=1;
    while(--cnt){
        vis[t]=1;
        s=t;
        for(int x=s;x;x=lk[x]){
            for(int i=0;i<G[x].size();i++){
                int to=Find(G[x][i].to),w=G[x][i].w;
                if(!vis[to]){
                    val[to]+=w;
                    q.push({val[to],to});
                }
            }
        }
        t=0;
        while(!t){
            if(q.empty())return 0;
            ll ft=q.top().first;
            int st=q.top().second;
            q.pop();
            if(val[st]==ft){
                t=st;
            }
        }
    }
    return val[t];
}
ll StoerWanger(){
    ll ans=INF;
    int s,t;
    for(int i=n;i>1;i--){
        ans=min(ans,msp(i,s,t));
        if(ans==0)break;
        Union(s,t);
    }
    return ans;
}
int w33ha(){
    for(int i=1;i<=n;i++){
        f[i]=i;
        lk[i]=0;
        G[i].clear();
    }
    for(int i=1;i<=m;i++){
        int u,v,w;scanf("%d%d%d",&u,&v,&w);
        G[u].push_back((edge){v,w});
        G[v].push_back((edge){u,w});
    }
    printf("%lld\n",StoerWanger());
    return 0;
}
int main(){
    while(scanf("%d%d",&n,&m)!=EOF)w33ha();
    return 0;
}

发布了302 篇原创文章 · 获赞 19 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/dxyinme/article/details/102617443