Problem Description
度度熊国王率领着喵哈哈族的勇士,准备进攻哗啦啦族。哗啦啦族是一个强悍的民族,里面有充满智慧的谋士,拥有无穷力量的战士。所以这一场战争,将会十分艰难。为了更好的进攻哗啦啦族,度度熊决定首先应该从内部瓦解哗啦啦族。第一步就是应该使得哗啦啦族内部不能同心齐力,需要内部有间隙。哗啦啦族一共有n个将领,他们一共有m个强关系,摧毁每一个强关系都需要一定的代价。现在度度熊命令你需要摧毁一些强关系,使得内部的将领,不能通过这些强关系,连成一个完整的连通块,以保证战争的顺利进行。请问最少应该付出多少的代价。Input本题包含若干组测试数据。第一行两个整数n,m,表示有n个将领,m个关系。接下来m行,每行三个整数u,v,w。表示u将领和v将领之间存在一个强关系,摧毁这个强关系需要代价w数据范围:2<=n<=30001<=m<=1000001<=u,v<=n1<=w<=1000Output对于每组测试数据,输出最小需要的代价。Sample Input2 11 2 13 31 2 51 2 42 3 3Sample Output13题意
如上
题解
做法1.求全局最小割,由于点多边少,得用SW+堆优化(nmlogm)
做法2.S=1,随机T,求最小割,考虑到两个集合a和b,1肯定在a或b集合,也就是说随机的点只要在另外一个集合上,就有可能跑出最小割,特别要注意的是如果2999+1或者2998+2,会被卡到,所以可以特判掉这两种情况,另外>=3个点的概率还是挺高的(雾)
代码
SW+堆优化8080ms
1 #include2 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 >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 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
随机算法2402ms
1 #include2 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\n",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