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 }