zoukankan      html  css  js  c++  java
  • HDU 6081 度度熊的王国战略(全局最小割堆优化)

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

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

    数据范围:
    2<=n<=3000
    1<=m<=100000
    1<=u,v<=n
    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.求全局最小割,由于点多边少,得用SW+堆优化(nmlogm)

    做法2.S=1,随机T,求最小割,考虑到两个集合a和b,1肯定在a或b集合,也就是说随机的点只要在另外一个集合上,就有可能跑出最小割,特别要注意的是如果2999+1或者2998+2,会被卡到,所以可以特判掉这两种情况,另外>=3个点的概率还是挺高的(雾)

    代码

    SW+堆优化8080ms

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn=3010;
     5 const int maxm=2e5+5;
     6 const int INF=0x3f3f3f3f;
     7 
     8 int FIR[maxn],TO[maxm],NEXT[maxm],W[maxm],tote;
     9 bool vis[maxn];
    10 int F[maxn],link[maxn],wage[maxn];
    11 int n,m;
    12 
    13 void add(int u,int v,int w)
    14 {
    15     TO[tote]=v;
    16     W[tote]=w;
    17     NEXT[tote]=FIR[u];
    18     FIR[u]=tote++;
    19     
    20     TO[tote]=u;
    21     W[tote]=w;
    22     NEXT[tote]=FIR[v];
    23     FIR[v]=tote++;
    24 }
    25 int Find(int x)
    26 {
    27     return x==F[x]?x:F[x]=Find(F[x]);
    28 }
    29 void Join(int u,int v)
    30 {
    31     int p=u;
    32     while(link[p]!=-1)p=link[p];
    33     link[p]=v;
    34     F[v]=u;
    35 }
    36 int MinCut(int cnt,int &s,int &t)
    37 {
    38     memset(wage,0,sizeof wage);
    39     memset(vis,false,sizeof vis);
    40     priority_queue< pair<int,int> >q;
    41     t=1;
    42     while(--cnt)
    43     {
    44         vis[s=t]=true;
    45         for(int u=s;u!=-1;u=link[u])
    46         {
    47             for(int p=FIR[u];p!=-1;p=NEXT[p])
    48             {
    49                 int v=Find(TO[p]);
    50                 if(!vis[v])
    51                     q.push(make_pair(wage[v]+=W[p],v));
    52             }
    53         }
    54         t=0;
    55         while(!t)
    56         {
    57             if(q.empty())return 0;
    58             pair<int,int> pa=q.top();q.pop();
    59             if(wage[pa.second]==pa.first)
    60                 t=pa.second;
    61         }
    62     }
    63     return wage[t];
    64 }
    65 int Stoer_Wagner()
    66 {
    67     int res=INF;
    68     for(int i=n,s,t;i>1;i--)
    69     {
    70         res=min(res,MinCut(i,s,t));
    71         if(res==0)break;
    72         Join(s,t);
    73     }
    74     return res;
    75 }
    76 void init()
    77 {
    78     tote=0;
    79     for(int i=1;i<=n;i++)FIR[i]=link[i]=-1,F[i]=i;
    80 }
    81 int main()
    82 {
    83     while(scanf("%d%d",&n,&m)!=EOF)
    84     {
    85         init();
    86         for(int i=0,u,v,w;i<m;i++)
    87         {
    88             scanf("%d%d%d",&u,&v,&w);
    89             add(u,v,w);
    90         }
    91         printf("%d
    ",Stoer_Wagner());
    92     }
    93     return 0;
    94 }

    随机算法2402ms

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn=3005;
     5 const int maxm=2e5+5;//至少总M*2
     6 const int INF=0x3f3f3f3f;
     7 
     8 int TO[maxm],CAP[maxm],NEXT[maxm],tote;
     9 int FIR[maxn],gap[maxn],cur[maxn],d[maxn],q[400000],u[maxm],v[maxm],w[maxm];
    10 int n,m,S,T;
    11 
    12 void add(int u,int v,int cap)
    13 {
    14     //printf("i=%d %d %d %d
    ",tote,u,v,cap);
    15     TO[tote]=v;
    16     CAP[tote]=cap;
    17     NEXT[tote]=FIR[u];
    18     FIR[u]=tote++;
    19     
    20     TO[tote]=u;
    21     CAP[tote]=0;
    22     NEXT[tote]=FIR[v];
    23     FIR[v]=tote++;
    24 }
    25 void bfs()
    26 {
    27     memset(gap,0,sizeof gap);
    28     memset(d,0,sizeof d);
    29     ++gap[d[T]=1];
    30     for(int i=1;i<=n;++i)cur[i]=FIR[i];
    31     int head=1,tail=1;
    32     q[1]=T;
    33     while(head<=tail)
    34     {
    35         int u=q[head++];
    36         for(int v=FIR[u];v!=-1;v=NEXT[v])
    37             if(!d[TO[v]])
    38                 ++gap[d[TO[v]]=d[u]+1],q[++tail]=TO[v];
    39     }
    40 }
    41 int dfs(int u,int fl)
    42 {
    43     if(u==T)return fl;
    44     int flow=0;
    45     for(int &v=cur[u];v!=-1;v=NEXT[v])
    46         if(CAP[v]&&d[u]==d[TO[v]]+1)
    47         {
    48             int Min=dfs(TO[v],min(fl,CAP[v]));
    49             flow+=Min,fl-=Min,CAP[v]-=Min,CAP[v^1]+=Min;
    50             if(!fl)return flow;
    51         }
    52     if(!(--gap[d[u]]))d[S]=n+1;
    53     ++gap[++d[u]],cur[u]=FIR[u];
    54     return flow;
    55 }
    56 int ISAP()
    57 {
    58     bfs();
    59     int ret=0;
    60     while(d[S]<=n)ret+=dfs(S,INF);
    61     return ret;
    62 }
    63 void init()
    64 {
    65     tote=0;
    66     memset(FIR,-1,sizeof FIR);
    67 }
    68 int main()
    69 {
    70     srand(time(NULL));
    71     while(scanf("%d%d",&n,&m)!=EOF)
    72     {
    73         int wage[maxn]={0};
    74         for(int i=0;i<m;i++)
    75         {
    76             scanf("%d%d%d",&u[i],&v[i],&w[i]);
    77             wage[u[i]]+=w[i];
    78             wage[v[i]]+=w[i];
    79         }
    80         int sj[maxn];
    81         for(int i=1;i<n;i++)sj[i]=i+1;
    82         random_shuffle(sj+1,sj+n);
    83         int ans=1e9;
    84         for(int i=1;i<=n;i++)ans=min(ans,wage[i]);
    85         if(n!=2)for(int i=0;i<m;i++)ans=min(ans,wage[u[i]]+wage[v[i]]-2*w[i]);
    86         S=1;
    87         for(int i=1;i<=min(500,n-1);i++)
    88         {
    89             T=sj[i];
    90             init();
    91             for(int j=0;j<m;j++)
    92                 add(u[j],v[j],w[j]),add(v[j],u[j],w[j]);    
    93             ans=min(ans,ISAP());
    94         }
    95         printf("%d
    ",ans);
    96     }
    97     return 0;
    98 }
  • 相关阅读:
    eclipse debug小技巧
    session.flush加锁测试.
    mac os x升级MOUNTAIN LION后svn command not found的解决
    Linux下vi命令大全(转)
    Java 集合框架
    java 实用类
    Java 输入/输出 反射
    Java 注解
    多线程(重点)
    多线程
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/9607436.html
Copyright © 2011-2022 走看看